#include "CenterBattleManager.h"
#include "StringConverter.h"
#include "ResourceManager.h"
#include "Database/DatabaseEnv.h"
#include "StringConverter.h"
#include "json/json.h"
#include "NGLog.h"
#include "Character.h"
#include "CharManager.h"
#include "Items.h"
#include "ItemManager.h"
#include "Users.h"
#include "UserManager.h"
#include "Channels.h"
#include "ChannelManager.h"
#include "Towns.h"
#include "TownManager.h"
#include "ItemModelManager.h"
#include "Message.h"
#include "CenterBankManager.h"
#include "VipCardManager.h"
#include "Tools.h"
#include "XMLData.h"
#include "GameDefine.h"
#include XMLDATA_MGR_PATH
#include LOGIC_MGR_PATH
#include LOG_MGR_PATH
#include PROTOCOLS_MGR_PATH
#include "OpcodesEx.h"
#include "WorldPacket.h"
#include "AIInterface.h"
#include "WSSocketManager.h"
#include "json/json.h"
#include "ProtocolDealEnums.h"
#include "url.h"
#include "CRUsersManager.h"
#include "DataTransferManager.h"
#include "CenterClubManager.h"

#ifdef CENTERMATCH
	#include "CenterMatchManager.h"
#endif

CenterBattleManager::CenterBattleManager()
{
	m_mapCenterBattle.clear();
	m_mapChangeTableTimer.clear();
}

//=============================组局信息相关===================================
bool CenterBattleManager::AddCenterBattle(CenterBattle & cb)
{
	Fields fields;
	sDataMgr.initData(DataManager::DatabaseTypeCenter, DB_NAME_CENTERBATTLE, &fields);
	
	fields["group_id"] = 1;
	fields["gz_id"] = cb.gz_id;
	fields["game_id"] = cb.game_id;
	fields["status"] = cb.status;
	fields["pid"] = cb.pid;
	fields["club_id"] = cb.club_id;
	fields["club_room_id"] = cb.club_room_id;
	fields["reg_from"] = cb.reg_from;
	fields["openid"] = cb.openid;
	fields["battle_name"] = cb.battle_name;
	fields["name"] = cb.name;
	fields["head"] = cb.head;
	
	fields["istrack"] = cb.istrack;
	fields["curr_loop"] = cb.curr_loop;
	fields["limit_loop"] = cb.limit_loop;
	fields["limit_time"] = cb.limit_time;
	fields["top_times"] = cb.top_times;
	fields["coins_model"] = cb.coins_model;
	fields["init_coins"] = cb.init_coins;
	fields["limit_coins"] = cb.limit_coins;
	fields["base_coins"] = cb.base_coins;
	fields["fan_coins"] = cb.fan_coins;
	fields["think_time"] = cb.think_time;
	fields["timeout"] = cb.timeout;
	fields["pause"] = cb.pause;
	fields["start_time"] = cb.start_time;
	fields["max_player"] = cb.max_player;
	fields["channel_id"] = cb.channel_id;
	fields["mode"] = cb.mode;
	fields["pay_mode"] = cb.pay_mode;
	fields["join_code"] = cb.join_code;
	fields["create_time"] = cb.create_time;
	fields["end_time"] = cb.end_time;
	fields["player"] = cb.player;
	fields["black_list"] = cb.black_list;
	
	fields["data1"] = cb.data1;
	fields["data2"] = cb.data2;
	fields["data3"] = cb.data3;
	fields["data4"] = cb.data4;
	fields["data5"] = cb.data5;
	fields["data6"] = cb.data6;
	fields["data7"] = cb.data7;
	fields["data8"] = cb.data8;
	fields["sdata1"] = cb.sdata1;
	fields["sdata2"] = cb.sdata2;
	fields["sdata3"] = cb.sdata3;
	fields["sdata4"] = cb.sdata4;
	fields["sdata5"] = cb.sdata5;
	fields["sdata6"] = cb.sdata6;
	fields["sdata7"] = cb.sdata7;
	fields["sdata8"] = cb.sdata8;
	fields["update_key"] = cb.update_key;
	
	Log.Debug("CenterBattleManager::AddCenterBattle","update_key[%u] mode[%u]", cb.update_key, cb.mode);
	if (!sDataMgr.insertData(DataManager::DatabaseTypeCenter, DB_NAME_CENTERBATTLE, &fields))
		return false;
	
	cb.cb_id = fields["cb_id"].GetUInt32();
	return true;
}


bool CenterBattleManager::UpdateCenterBattle(const CenterBattle & cb_org, uint32 update_key)
{
	int count = 0;
	uint8 update_times = 0;
	
	CenterBattle cb = cb_org;
	
	while(update_times++ < 5)
	{
		Fields fields;
		fields["status"] = cb_org.status;
		fields["curr_loop"] = cb_org.curr_loop;
		fields["start_time"] = cb_org.start_time;
		fields["max_player"] = cb_org.max_player;
		fields["channel_id"] = cb_org.channel_id;
		fields["mode"] = cb_org.mode;
		fields["pay_mode"] = cb_org.pay_mode;
		fields["join_code"] = cb_org.join_code;
		fields["create_time"] = cb_org.create_time;
		fields["end_time"] = cb_org.end_time;
		fields["player"] = cb_org.player;
		fields["data3"] = cb_org.data3;
		fields["data4"] = cb_org.data4;
		fields["data5"] = cb_org.data5;
		fields["data6"] = cb_org.data6;
		fields["data7"] = cb_org.data7;
		fields["data8"] = cb_org.data8;
		fields["sdata1"] = cb_org.sdata1;
		fields["sdata2"] = cb_org.sdata2;
		fields["sdata3"] = cb_org.sdata3;
		fields["sdata4"] = cb_org.sdata4;
		fields["sdata5"] = cb_org.sdata5;
		fields["sdata6"] = cb_org.sdata6;
		fields["sdata7"] = cb_org.sdata7;
		fields["sdata8"] = cb_org.sdata8;
		fields["update_key"] = cb.update_key + 1;
		Log.Debug("CenterBattleManager::UpdateCenterBattle","cb_id[%u] cb.update_key[%u] mode[%u] player[%s]", 
									cb_org.cb_id, cb.update_key, cb_org.mode, cb_org.player.c_str());
		
		count = sDataMgr.updateDataQueryAffected(DataManager::DatabaseTypeCenter, DB_NAME_CENTERBATTLE, 
									&fields, "`cb_id` = %u and `update_key` = %u", cb_org.cb_id, cb.update_key);
		
		if(count <= 0)
		{// 更新失败重新读取数据
			GetCenterBattle(cb.cb_id, &cb);
			Sleep(10);
			continue;
		}
		else
		{
			break;
		}
	}
	
	return count > 0;
}

#define SQLBUFER_LEN 16384

bool CenterBattleManager::UpdateCenterBattle(Fields * fields, const char * QueryString, ...)
{
	char sql[SQLBUFER_LEN] = ""; 
	va_list vlist; 
	va_start(vlist, QueryString); 
	vsnprintf(sql, SQLBUFER_LEN, QueryString, vlist); 
	va_end(vlist);
	int count = sDataMgr.updateDataQueryAffected(DataManager::DatabaseTypeCenter, DB_NAME_CENTERBATTLE, fields, sql);
	return count > 0;
}

bool CenterBattleManager::UpdateCenterBattle(const uint32 &cb_id, const uint32 & update_key, Fields * fields)
{
	CenterBattle cb;
	GetCenterBattle(cb_id, &cb);
	(*fields)["update_key"] = cb.update_key + 1;
	
	int count = sDataMgr.updateDataQueryAffected(DataManager::DatabaseTypeCenter, DB_NAME_CENTERBATTLE, fields, 
												"`cb_id` = %u and `update_key` = %u", cb_id, cb.update_key);
	
	if(count > 0)
		return true;
	
	// 尝试几次更新
	uint8 update_count = 0;
	while(++update_count < 3)
	{
		CenterBattle cb2;
		GetCenterBattle(cb_id, &cb2);
		
		(*fields)["update_key"] = cb2.update_key + 1;
		int count = sDataMgr.updateDataQueryAffected(DataManager::DatabaseTypeCenter, DB_NAME_CENTERBATTLE, fields, 
													"`cb_id` = %u and `update_key` = %u", cb_id, cb2.update_key);
		// 重复尝试更新成功
		if(count > 0)
			return true;
	}
	
	return false;
}


bool CenterBattleManager::GetCenterBattle(const uint32 &cb_id, CenterBattle * cb)
{
	assert (cb);
	FieldRows rows;
	sDataMgr.getDatas(DataManager::DatabaseTypeCenter, DB_NAME_CENTERBATTLE, &rows, "`cb_id` = %u", cb_id);
	if (rows.empty())
		return false;
	
	Fields fields = rows.front();
	cb->cb_id = fields["cb_id"].GetUInt32();
	cb->group_id = fields["group_id"].GetUInt32();
	cb->gz_id = fields["gz_id"].GetUInt32();
	cb->game_id = fields["game_id"].GetUInt32();
	cb->status = fields["status"].GetUInt32();
	cb->pid = fields["pid"].GetUInt32();
	cb->club_id = fields["club_id"].GetUInt64();
	cb->club_room_id = fields["club_room_id"].GetUInt64();
	cb->reg_from = fields["reg_from"].GetUInt32();
	
	cb->openid = fields["openid"].GetUInt32();
	cb->battle_name = fields["battle_name"].GetValue();
	cb->name = fields["name"].GetValue();
	cb->head = fields["head"].GetValue();
	
	cb->istrack = fields["istrack"].GetUInt32();
	cb->curr_loop = fields["curr_loop"].GetUInt32();
	cb->limit_loop = fields["limit_loop"].GetUInt32();
	cb->limit_time = fields["limit_time"].GetUInt32();
	cb->top_times = fields["top_times"].GetUInt32();
	cb->coins_model = fields["coins_model"].GetUInt32();
	cb->init_coins = fields["init_coins"].GetUInt32();
	cb->limit_coins = fields["limit_coins"].GetUInt32();
	cb->base_coins = fields["base_coins"].GetUInt32();
	cb->fan_coins = fields["fan_coins"].GetUInt32();
	cb->think_time = fields["think_time"].GetUInt32();
	cb->timeout = fields["timeout"].GetUInt32();
	cb->pause = fields["pause"].GetUInt32();
	cb->start_time = fields["start_time"].GetUInt32();
	cb->max_player = fields["max_player"].GetUInt32();
	cb->channel_id = fields["channel_id"].GetUInt32();
	cb->mode = fields["mode"].GetUInt32();
	cb->pay_mode = fields["pay_mode"].GetUInt32();
	cb->join_code = fields["join_code"].GetValue();
	cb->create_time = fields["create_time"].GetValue();
	cb->end_time = fields["end_time"].GetValue();
	cb->player = fields["player"].GetValue();
	cb->black_list = fields["black_list"].GetValue();
	
	cb->data1 = fields["data1"].GetUInt32();
	cb->data2 = fields["data2"].GetUInt32();
	cb->data3 = fields["data3"].GetInt32();
	cb->data4 = fields["data4"].GetInt32();
	cb->data5 = fields["data5"].GetInt32();
	cb->data6 = fields["data6"].GetInt32();
	cb->data7 = fields["data7"].GetInt32();
	cb->data8 = fields["data8"].GetInt32();
	cb->sdata1 = fields["sdata1"].GetValue();
	cb->sdata2 = fields["sdata2"].GetValue();
	cb->sdata3 = fields["sdata3"].GetValue();
	cb->sdata4 = fields["sdata4"].GetValue();
	cb->sdata5 = fields["sdata5"].GetValue();
	cb->sdata6 = fields["sdata6"].GetValue();
	cb->sdata7 = fields["sdata7"].GetValue();
	cb->sdata8 = fields["sdata8"].GetValue();
	cb->update_key = fields["update_key"].GetUInt32();
	return true;
}

uint32 CenterBattleManager::GetCenterBattleList(std::list<CenterBattle> * lstData, const char * query,...)
{
	va_list argp;
	va_start(argp, query);
	lstData->clear();
	FieldRows fieldRows;
	
	char sql[SQLBUFER_LEN] = ""; 
	va_list vlist; 
	va_start(vlist, query); 
	vsnprintf(sql, SQLBUFER_LEN, query, vlist); 
	va_end(vlist);
	
	if (!sDataMgr.getDatas(DataManager::DatabaseTypeCenter, DB_NAME_CENTERBATTLE, &fieldRows, sql))
		return 0;
	
	FieldRows::iterator iter, enditer = fieldRows.end();
	for (iter = fieldRows.begin(); iter != enditer; ++ iter)
	{
		CenterBattle cb;
		Fields &fields = *iter;
		
		cb.cb_id = fields["cb_id"].GetUInt32();
		cb.group_id = fields["group_id"].GetUInt32();
		cb.gz_id = fields["gz_id"].GetUInt32();
		cb.game_id = fields["game_id"].GetUInt32();
		cb.status = fields["status"].GetUInt32();
		cb.pid = fields["pid"].GetUInt32();
		cb.club_id = fields["club_id"].GetUInt64();
		cb.club_room_id = fields["club_room_id"].GetUInt64();
		cb.reg_from = fields["reg_from"].GetUInt32();
		
		cb.openid = fields["openid"].GetUInt32();
		cb.battle_name = fields["battle_name"].GetValue();
		cb.name = fields["name"].GetValue();
		cb.head = fields["head"].GetValue();
		
		cb.istrack = fields["istrack"].GetUInt32();
		cb.curr_loop = fields["curr_loop"].GetUInt32();
		cb.limit_loop = fields["limit_loop"].GetUInt32();
		cb.limit_time = fields["limit_time"].GetUInt32();
		cb.top_times = fields["top_times"].GetUInt32();
		cb.coins_model = fields["coins_model"].GetUInt32();
		cb.init_coins = fields["init_coins"].GetUInt32();
		cb.limit_coins = fields["limit_coins"].GetUInt32();
		cb.base_coins = fields["base_coins"].GetUInt32();
		cb.fan_coins = fields["fan_coins"].GetUInt32();
		cb.think_time = fields["think_time"].GetUInt32();
		cb.timeout = fields["timeout"].GetUInt32();
		cb.pause = fields["pause"].GetUInt32();
		cb.start_time = fields["start_time"].GetUInt32();
		cb.max_player = fields["max_player"].GetUInt32();
		cb.channel_id = fields["channel_id"].GetUInt32();
		cb.mode = fields["mode"].GetUInt32();
		cb.pay_mode = fields["pay_mode"].GetUInt32();
		cb.join_code = fields["join_code"].GetValue();
		cb.create_time = fields["create_time"].GetValue();
		cb.end_time = fields["end_time"].GetValue();
		cb.player = fields["player"].GetValue();
		cb.black_list = fields["black_list"].GetValue();
		
		cb.data1 = fields["data1"].GetUInt32();
		cb.data2 = fields["data2"].GetUInt32();
		cb.data3 = fields["data3"].GetInt32();
		cb.data4 = fields["data4"].GetInt32();
		cb.data5 = fields["data5"].GetInt32();
		cb.data6 = fields["data6"].GetInt32();
		cb.data7 = fields["data7"].GetInt32();
		cb.data8 = fields["data8"].GetInt32();
		cb.sdata1 = fields["sdata1"].GetValue();
		cb.sdata2 = fields["sdata2"].GetValue();
		cb.sdata3 = fields["sdata3"].GetValue();
		cb.sdata4 = fields["sdata4"].GetValue();
		cb.sdata5 = fields["sdata5"].GetValue();
		cb.sdata6 = fields["sdata6"].GetValue();
		cb.sdata7 = fields["sdata7"].GetValue();
		cb.sdata8 = fields["sdata8"].GetValue();
		cb.update_key = fields["update_key"].GetInt32();
		
		lstData->push_back(cb);
	}
	
	return lstData->size();
}

void CenterBattleManager::Update()
{
	if(!m_nPreUpdateTimer)
	{
		m_nPreUpdateTimer = time(0);
	}
	else
	{
		uint32 time_now = time(0);
		if(time_now - m_nPreUpdateTimer >= sXmlDataMgr.GetConfXMLValue("CHECK_EROOR_BATTLE_TIMER"))
		{// 5分钟检测一次
		
		WGS_CENTERBATTLE_LOCK
			
			// 检查创建失败的牌桌
			std::list<CenterBattle> lstData;
			GetCenterBattleList(&lstData, "`status` = %u and start_time < %u", enBattleStatus_Require, m_nPreUpdateTimer);
			if(lstData.size())
			{
				std::list<CenterBattle>::iterator iter,ei = lstData.end();
				for(iter = lstData.begin(); iter!=ei; ++iter)
				{
					Log.Debug("CenterBattleManager::Update","cb_id[%u] delete create failed battle!", (*iter).cb_id);
					CenterBattle cb = *iter;
					stCenterBattleOpenCoins stCBOC = sXmlDataMgr.GetCenterBattleOpenCoins((*iter).reg_from, (*iter).game_id, (*iter).limit_loop, enCenterBattleLimitType_Loop, (*iter).mode);
					
					std::map<uint32, uint32> mapItems;
					
					String item_name = sXmlDataMgr.GetItemModelNameByAgentID(cb.reg_from, cb.data1);
					String szTitle = "";
					char buf[256] = "";
					if((*iter).data1 && (*iter).pay_mode == enPayMode_FangZhu)
					{
						const MailModel *pModel = sXmlDataMgr.GetMailModel("CENTER_BATTLE_ERROR");
						if(pModel)
						{
							szTitle = pModel->szTitle;
							String szContent = pModel->szContent;
							
							//  您于%s创建的【%s】的牌局创建失败，返还您费用%sx%u！
							sprintf(buf, szContent.c_str(), (*iter).create_time.c_str(), stCBOC.desc.c_str(), item_name.c_str(), (*iter).data2);
						}
					}
					else
					{
						const MailModel *pModel = sXmlDataMgr.GetMailModel("CENTER_BATTLE_ERROR_FREE");
						if(pModel)
						{
							szTitle = pModel->szTitle;
							String szContent = pModel->szContent;
							
							//  您于%s创建的【%s】的牌局创建失败，返还您费用%sx%u！
							sprintf(buf, szContent.c_str(), (*iter).create_time.c_str(), stCBOC.desc.c_str());
						}
					}
					
					// AA制和房主全额制退房费（直接加，不以邮件附件来）
					if(cb.data1 > 0)
					{
						Json::Value valPay;
						Json::Reader reader;
						Json::FastWriter w;
						reader.parse(cb.sdata4, valPay);
						
						if(cb.pay_mode != enPayMode_FangZhu)
						{// 其他付费机制
							
						}
						else
						{// 房主全额制
							for(Json::Value::iterator iterVal=valPay.begin(); iterVal!=valPay.end(); ++iterVal)
							{
								uint32 gz_id = (*iterVal)["gz_id"].asUInt();
								uint32 game_id = sGLMgr.GetTargetServerGameid(gz_id, cb.reg_from);
								if(sXmlDataMgr.IsInGameIds(game_id))
								{// 房主在同一服务器
									uint32 char_id = (*iterVal)["cid"].asUInt();
									CharPtr pChr = sCharMgr.load(char_id);
									if(pChr.isNull())
										break;
									
									sGLMgr.addItemNum(pChr, cb.data1, cb.data2);
									sLogDataMgr.UpdateItemsInfoLog(pChr, en_ST_ReturnCenterBattleOpenCoins, cb.data1, en_UNT_Add, cb.data2, cb.cb_id);
									
									uint32 pid = (*iterVal)["pid"].asUInt();
									sGLMgr.CreateMail(pid, szTitle, buf, 0, en_ST_ReturnCenterBattleOpenCoins, &mapItems);
								}
								else
								{// 给棋牌圈玩家加上房卡
									Json::Value valData = (*iterVal);
									
									valData["cb_id"] = cb.cb_id;
									valData["mail_title"] = szTitle;
									valData["content"] = buf;
									valData["agent_id"] = cb.reg_from;
									
									String strData = w.write(valData);
									sGLMgr.SendAddItemGateway(strData);
								}
							}
						}
					}
					else
					{
						sGLMgr.CreateMail(cb.pid, szTitle, buf, 0, en_ST_ReturnCenterBattleOpenCoins, &mapItems);
					}
					
					sLogDataMgr.CreateCenterBattleLog((*iter).pid, (*iter).cb_id, (*iter).game_id, (*iter).gz_id, (*iter).data1, (*iter).data2, enCenterBattleReturnGold_CreateError, (*iter).curr_loop, (*iter).curr_loop == (*iter).limit_loop, (*iter).mode);
					
					(*iter).status = enBattleStatus_Delete;
					(*iter).end_time = sGLMgr.GetCurDateTime();
					UpdateCenterBattle(*iter);
				}
			}
			
			lstData.clear();
			
			//  重启删除失败的牌桌
			uint32 channel_overtime = sXmlDataMgr.GetConfXMLValue("CENTER_BATTLE_MAX_WAITTIMER");
			
			GetCenterBattleList(&lstData, "`status` < %u and start_time < %u and data5 = 0", enBattleStatus_Delete, time_now - channel_overtime);
			if(lstData.size())
			{
				std::list<CenterBattle>::iterator iter,ei = lstData.end();
				for(iter = lstData.begin(); iter!=ei; ++iter)
				{
					Log.Debug("CenterBattleManager::Update","cb_id[%u] restart server not delete!", (*iter).cb_id);
					(*iter).status = enBattleStatus_Delete;
					(*iter).end_time = sGLMgr.GetCurDateTime();
					UpdateCenterBattle(*iter);
				}
			}
			
			m_nPreUpdateTimer = time_now;
		}
	}
}

// 用Json数据创建组局
bool CenterBattleManager::PlayerCreateCenterBattle(CharPtr & pChr, String strData)
{
	if(pChr.isNull() || strData == "")
		return false;
	
WGS_CENTERBATTLE_LOCK
	UserPtr pUser = sUserMgr.getByHandle(pChr->getUInt32Field("userid"));
	if(pUser.isNull())
		return false;
	
	Json::Value val;
	Json::Reader reader;
	reader.parse(strData, val);
	
	if(val.empty())
		return false;
	
	// 分区ID
	uint32 gz_id = 0;							
	if(val.isMember("gz_id"))
		gz_id = val["gz_id"].asUInt();
	
	// 游戏ID
	uint32 game_id = 0;							
	if(val.isMember("game_id"))
		game_id = val["game_id"].asUInt();
	
	// 底分
	uint32 base_coins = sXmlDataMgr.GetConfXMLValue("CENTER_BATTLE_LEAST_BASECOINS");
	if(val.isMember("base_coins"))
		base_coins = val["base_coins"].asUInt();
	
	// 游戏玩法
	uint32 mode = 0;
	if(val.isMember("mode_id"))
		mode = val["mode_id"].asUInt();
	
	// 房费模式ID
	uint32 money_type = 0;
	if(val.isMember("money_type"))
		money_type = val["money_type"].asUInt();
	
	// 限制局数
	uint32 round_num = 0;
	if(val.isMember("round_num"))
		round_num = val["round_num"].asUInt();
	
	// 封顶
	uint32 top_times = 0;
	if(val.isMember("limit"))
		top_times = val["limit"].asUInt();
	
	// 房主名称
	String name = pChr->getStringField("name");
	
	// 房间名称
	String battle_name = "";
	if(val.isMember("room_name"))
		battle_name = string_url_encode(val["room_name"].asString());
	
	// 游戏玩法设定
	Json::Value val_extra;
	if(val.isMember("extra_data"))
		val_extra = val["extra_data"];
	
	// 付费模式（1 房主模式，2 AA制 3 扣对局费）
	uint32 pay_mode = 1;
	if(val.isMember("pay_mode"))
		pay_mode = val["pay_mode"].asUInt();
	
	// 公开房（0 私有 1 公开）
	uint32 isPublic = 0;
	if(val.isMember("isPublic"))
		isPublic = val["isPublic"].asUInt();
	
	// 进入线
	uint32 join_limit = 0;
	if(val.isMember("ticket_coins"))
		join_limit = val["ticket_coins"].asUInt();
	
	// 离开线
	uint32 leave_limit = 0;
	if(val.isMember("exit_coins"))
		leave_limit = val["exit_coins"].asUInt();
	
	// 中途加入（默认是可以的）
	uint32 zhongtujiaru = 1;
	if(val.isMember("isZhongTuJiaRu"))
		zhongtujiaru = val["isZhongTuJiaRu"].asUInt();
	
	// 允许观战
	uint32 guanzhan = 0;
	if(val.isMember("isGuanZhan"))
		guanzhan = val["isGuanZhan"].asUInt();
	
	// 俱乐部ID
	uint32 club_id = 0;
	if(val.isMember("club_id"))
		club_id = val["club_id"].asUInt();
	
	// 俱乐部房间ID
	uint32 club_room_id = 0;
	if(val.isMember("club_room_id"))
		club_room_id = val["club_room_id"].asUInt();
	
	// 限制时间
	uint32 limit_time = 0;
	if(val.isMember("limit_time"))
		limit_time = val["limit_time"].asUInt();
	
	bool isInHuoDong = false;
	uint32 time_zero = time(0);
	CenterBattle cb;
	uint8 result = enResult_Sucess;
	std::list<CenterBattle> lstData;
	do
	{
		uint32 playing_count = GetCenterBattleList(&lstData, "pid = %u and status < 255", pUser->getUInt32Field("platform_id"));
		if(playing_count >= sXmlDataMgr.GetConfXMLValue("MAX_CENTER_BATTLE_COUNT"))
		{// 创建牌局数量超过限制
			result = enCreateBattle_OverLimitCount;
			break;
		}
		
		stCenterBattleMode stMode = sXmlDataMgr.GetCenterBattleModeByGameid(game_id, mode);
		if(!stMode.game_id)
		{// 游戏玩法判断
			result = enCreateBattle_NoThisMode;
			break;
		}
		
		if(round_num == 0 && pay_mode != enPayMode_LoopPay)
		{// 必须设置一个限制条件
			result = enCreateBattle_NoLimit;
			break;
		}
		
		uint32 agent_id = pUser->getUInt32Field("reg_from");
		stCenterBattleOpenCoins stCBOC = sXmlDataMgr.GetCenterBattleOpenCoins(agent_id, game_id, money_type, 0, round_num, mode);
		Log.Debug("CenterBattleManager::PlayerCreateCenterBattle","agent_id[%u] game_id[%u] money_type[%u] round_num[%u] mode[%u]", 
														agent_id, game_id, money_type, round_num, mode);
		
		if(stCBOC.model_id == 0)
		{// 错误的配置
			result = enCreateBattle_ErrorLoop;
			break;
		}
		
		if(stCBOC.join_point_lsestMult && join_limit < stCBOC.join_point_lsestMult * base_coins)
		{// 进入限制分数太低
			result = enCreateBattle_NoLimit;
			break;
		}
		
		if(stCBOC.exit_point_lsestMult && leave_limit < stCBOC.exit_point_lsestMult * base_coins)
		{// 离开限制分数太低
			result = enCreateBattle_NoLimit;
			break;
		}
		
		if(club_id || club_room_id)
		{// 检测创建者权限和创建上限
			CenterClub cc;
			if(!sCenterClubMgr.GetCenterClub(club_id, &cc))
			{// 无效的俱乐部ID
				result = enCreateBattle_NoClubID;
				break;
			}
			
			if(stCBOC.use_club_diamand)
			{// 使用俱乐部钻石创建牌桌
				uint32 club_diamand = sCenterClubMgr.GetClubActivityValue(club_id);
				if(club_diamand < stCBOC.num)
				{// 俱乐部钻石不足
					result = enCreateBattle_GoldTicketNeed;
					break;
				}
			}
			else
			{
				if(!sCenterClubMemberMgr.IsPlayerClubManager(club_id, pUser->getUInt32Field("platform_id")))				
				{// 权限不足
					result = enCreateBattle_ClubQuanXian;
					break;
				}
			}
		}
		
		if(stCBOC.use_club_diamand && club_id)
		{// 扣除俱乐部钻石
			// 减少俱乐部活动经费
			if(!sCenterClubMgr.ReduceClubActivityValue(club_id, stCBOC.num))
			{
				result = enCreateBattle_GoldTicketNeed;
				break;
			}
		}
		else
		{// 玩家钻石
			if(time_zero >= stCBOC.free_begin_time && time_zero <= stCBOC.free_end_time)
			{// 免费
				isInHuoDong = true;
			}
			else
			{// 不免费
				if(join_limit && sGLMgr.GetItemNum(pChr, stCBOC.model_id) < join_limit)
				{// 低于带入限制
					result = enCreateBattle_GoldTicketNeed;
					break;
				}
				
				if(pay_mode == enPayMode_FangZhu)
				{// 房主付费模式
					if(!sGLMgr.reduceItemNum(pChr, stCBOC.model_id, stCBOC.num))
					{// 开局费不足
						result = enCreateBattle_GoldTicketNeed;
						break;
					}
				}
				else if(pay_mode == enPayMode_LoopPay)
				{// 收对局费模式
					Log.Debug("CenterBattleManager::PlayerCreateCenterBattle","model[%u] num[%u] join_limit[%u]", stCBOC.model_id, sGLMgr.GetItemNum(pChr, stCBOC.model_id), join_limit);
				}
			}
		}
		
		if(club_id && stCBOC.use_club_diamand)
		{
			cb.pid = sCenterClubMgr.GetClubCreaterPid(club_id);	// pid
			if(pUser->getUInt32Field("reg_from") == 5025)		// 枪王还是给创建者
				cb.pid = pUser->getUInt32Field("platform_id");
		}
		else
		{
			cb.pid = pUser->getUInt32Field("platform_id");		// pid
		}
		
		cb.reg_from = pUser->getUInt32Field("reg_from");	// reg_from
		cb.openid = pUser->getStringField("sdata1");		// openid
		
		cb.status = enBattleStatus_Require;					// 申请组局
		cb.gz_id = gz_id;
		cb.game_id = game_id;
		cb.base_coins = base_coins;
		cb.fan_coins = 0;
		cb.limit_loop = round_num;
		cb.club_id = club_id;						// 俱乐部ID
		cb.club_room_id = club_room_id;				// 俱乐部房间ID
		cb.top_times = top_times;
		cb.pause = false;
		cb.istrack = isPublic;						// 是否共开房（0 私有 1 公开）
		cb.start_time = time(0);
		cb.create_time = sGLMgr.GetCurDateTime();	// 创建时间
		cb.battle_name = battle_name;				// 房间名称
		cb.sdata2 = strData;						// 游戏玩法
		cb.mode = mode % 100;						// 游戏模式
		cb.pay_mode = pay_mode;						// 付费模式
		
		cb.data3 = zhongtujiaru;					// 中途加入（0 否 1 是）
		cb.data4 = guanzhan;						// 是否可以观战
		cb.name = pChr->getStringField("name");		// 房主昵称
		cb.head = pChr->getStringField("desc");		// 房主头像
		cb.update_key = 1;							// 数据更新锁
		
		if(!isInHuoDong)
		{// 没有免费活动
			cb.data1 = stCBOC.model_id;				// 开局费类型
			if(pay_mode == enPayMode_FangZhu)
				cb.data2 = stCBOC.num;				// 开局费数量
			else if(pay_mode == enPayMode_AAPay)
				cb.data2 = stCBOC.aa_num;			// AA值付费数量
		}
		
		if(cb.pay_mode == enPayMode_FangZhu)
		{// 记录房主扣费
			Json::Value valPlayer, valPay;
			if(club_id && stCBOC.use_club_diamand)
			{
				uint32 club_creater_pid = sCenterClubMgr.GetClubCreaterPid(club_id);
				uint32 club_creater_cid = 0;
				std::list<ResourcePtr> users;
				sUserMgr.getDBObjects(&users, 0, 1, "platform_id = %u and gz_id = %u ", club_creater_pid, pUser->getUInt32Field("gz_id"));
				if(users.size())
					club_creater_cid = (*users.begin())->getUInt32Field("char_id");
				
				valPlayer["pid"] = club_creater_pid;
				valPlayer["cid"] = club_creater_cid;
				valPlayer["gz_id"] = uint32(pUser->getUInt32Field("gz_id"));
			}
			else
			{
				valPlayer["pid"] = pUser->getUInt32Field("platform_id");
				valPlayer["cid"] = uint32(pChr->getHandle());
				valPlayer["gz_id"] = uint32(pChr->getUInt32Field("gz_id"));
			}
			valPlayer["model_id"] = cb.data1;
			valPlayer["num"] = cb.data2;
			
			valPay[0] = valPlayer;
			
			Json::FastWriter w;
			cb.sdata4 = w.write(valPay);
		}
		
		if(!AddCenterBattle(cb))
		{// 创建数据失败
			result = enCreateBattle_CreateDataField;
			// 房主全额制退房卡
			if(pay_mode == enPayMode_FangZhu)
				sGLMgr.addItemNum(pChr, stCBOC.model_id, stCBOC.num);
			
			break;
		}
	}
	while(0);
	
	Log.Debug("CenterBattleManager::PlayerCreateCenterBattle","player pid[%u] pay_mode[%u] result[%d]", pUser->getUInt32Field("platform_id"), pay_mode, result);
	
	// 发送创建组局结果（结果是成功 表示道指定分区服务器申请创建牌桌）
	WorldPacket packet;
	if(sProtocolsMgr.CreateRequireCenterBattleResultPacket(&packet, result))
		sGLMgr.SendProtocolsToChr(pChr,&packet);
	
	if(result == enResult_Sucess)
	{// 发送组局列表
		if(sProtocolsMgr.CreateCenterBattleInfoPacket(&packet, cb))
			sGLMgr.SendProtocolsToChr(pChr,&packet);
		
		// 记录创建日志
		sLogDataMgr.CreateCenterBattleLog(cb.pid, cb.cb_id, cb.game_id, cb.gz_id, cb.data1, cb.data2, enCenterBattleReturnGold_CreateSucess, cb.curr_loop, cb.curr_loop == cb.limit_loop, cb.mode);
		// 记录用户习惯
		Json::Value valCopy;
		valCopy["gz_id"] = gz_id;										// 分区ID
		valCopy["game_id"] = game_id;									// 游戏ID
		valCopy["club_id"] = club_id;									// 俱乐部ID
		valCopy["club_room_id"] = club_room_id;							// 俱乐部房间ID
		valCopy["base_coins"] = base_coins;								// 底分
		valCopy["fan_coins"] = 0;										// 翻分
		valCopy["istrack"] = 0;											// 跟踪（未用）
		valCopy["limit_loop"] = round_num;								// 限制轮次
		valCopy["limit_time"] = limit_time;								// 限制时间（未用）
		valCopy["top_times"] = top_times;								// 封顶
		valCopy["coins_model"] = 0;										// 初始带入的货币类型（未用）
		valCopy["init_coins"] = 0;										// 初始带入的货币数量（未用）
		valCopy["think_time"] = 0;										// 思考时间（未用）
		valCopy["timeout"] = 0;											// 牌桌超时时间（未用）
		valCopy["battle_name"] = battle_name;							// 房间名称
		valCopy["extra_data"] = strData;								// 玩法附加数据
		valCopy["mode"] = mode;											// 游戏玩法
		valCopy["pay_mode"] = pay_mode;									// 付费模式
		valCopy["pid"] = uint32(pUser->getUInt32Field("platform_id"));	// 用户PID
		
		Json::FastWriter w;
		String strConfig = w.write(valCopy);
		
		sCRUserConfigMgr.AddCenterBattleConfig(strConfig);
		
		// 网关创建牌桌
		Json::Value valUrl;
		valUrl["gz_id"] = gz_id;
		valUrl["pid"] = uint32(pUser->getUInt32Field("platform_id"));
		valUrl["cb_id"] = uint32(cb.cb_id);
		valUrl["agent_id"] = uint32(pUser->getUInt32Field("reg_from"));
		
		String strShareInfo = "";
		sGLMgr.SendCreateChannelGateway(pChr, w.write(valUrl), strConfig, strShareInfo);
		Log.Debug("CenterBattleManager::PlayerCreateCenterBattle","gz_id[%u]", gz_id);
	}
	
	return true;
}

// 机器人帮玩家创建组局
uint8 CenterBattleManager::RobotCreateCenterBattle(String strData, String & strExtraData, String & strShareInfo)
{
	if(strData == "")
		return enCreateBattle_EmprtParmas;
	
	Json::Value val;
	Json::Reader reader;
	reader.parse(strData, val);
	
	uint32 pid = 0;
	uint32 gz_id = 0;
	uint32 circle_gz_id = 0;
	uint32 mode = 0;
	uint32 game_id = 0;
	String strPlatform = "";
	
	if(val.isMember("pid"))
		pid = val["pid"].asUInt();
	
	if(pid == 0)
		return enCreateBattle_ErrorPid;
	
	if(val.isMember("gz_id"))
		gz_id = val["gz_id"].asUInt();
	
	if(val.isMember("circle_gz_id"))
		circle_gz_id = val["circle_gz_id"].asUInt();
	
	if(val.isMember("mode"))
	{
		mode = val["mode"].asUInt();
		mode %= 100;
	}
	
	if(val.isMember("game_id"))
		game_id = val["game_id"].asUInt();
	
	if(val.isMember("platform"))
		strPlatform = val["platform"].asString();
	
	Log.Debug("RobotCreateCenterBattle","gz_id[%u] game_id[%u]", gz_id, game_id);
	
WGS_CENTERBATTLE_LOCK
	std::list<ResourcePtr> users;
	sUserMgr.getDBObjects(&users, 0, 1, "platform_id = %u and gz_id = %u ", pid, circle_gz_id);
	if(users.empty())
		return enCreateBattle_ErrorPid;
	
	UserPtr pUser = sUserMgr.load((*users.begin())->getUInt32Field("uid"));
	if(pUser.isNull())
		return enCreateBattle_NoUser;
	
	GameBank bank;
	if (!sBankMgr.GetRealBank(pUser, bank))
		return enCreateBattle_NoBank;
	
	CharPtr pChr = sCharMgr.load(pUser->getUInt32Field("char_id"));
	if(pChr.isNull())
		return enCreateBattle_NoChar;
	
	// 没能成功登陆游戏，在其他游戏
	if(!sGLMgr.DisposeRobotAuthentication(pChr))
		return enCreateBattle_InOtherGame;
	
	Log.Debug("CenterBattleManager::RobotCreateCenterBattle","bank status[%u] bank gz_id[%u] user gz_id[%u]", bank.status, bank.gz_id, pUser->getUInt32Field("gz_id"));
	
	if(game_id == 0)
	{
		std::list<UserConfig> lstData;
		sCRUserConfigMgr.GetUserConfigList(&lstData, "pid = %u and status < 255", pid);
		if(lstData.size())
		{
			UserConfig uc = *lstData.begin();
			
			game_id = uc.last_gameid;
			gz_id = uc.last_gzid;
			mode = uc.last_mode;
		}
	}
	
	String strConfig = sCRUserConfigMgr.GetCenterBattleConfig(pid, game_id, mode);
	if(strConfig == "")
		return enCreateBattle_NoGzidInfo;
	
	Json::Value valConfig;
	reader.parse(strConfig, valConfig);
	
	uint32 base_coins = 0;
	if(valConfig.isMember("base_coins"))
		base_coins = valConfig["base_coins"].asUInt();
	
	uint32 pay_mode = 0;		// 付费模式（1 房主全额 2 AA制）
	if(valConfig.isMember("pay_mode"))
		base_coins = valConfig["pay_mode"].asUInt();
	
	uint32 fan_coins = 0;
	if(valConfig.isMember("fan_coins"))
		fan_coins = valConfig["fan_coins"].asUInt();
	
	uint32 limit_loop = 0;
	if(valConfig.isMember("limit_loop"))
		limit_loop = valConfig["limit_loop"].asUInt();
	
	if(valConfig.isMember("round_num"))
		limit_loop = valConfig["round_num"].asUInt();
	
	uint32 limit_time = 0;
	if(valConfig.isMember("limit_time"))
		limit_time = valConfig["limit_time"].asUInt();
	
	uint32 club_id = 0;
	if(valConfig.isMember("club_id"))
		club_id = valConfig["club_id"].asUInt();
	
	uint32 club_room_id = 0;
	if(valConfig.isMember("club_room_id"))
		club_room_id = valConfig["club_room_id"].asUInt();
	
	uint32 top_times = 0;
	if(valConfig.isMember("top_times"))
		top_times = valConfig["top_times"].asUInt();
	
	uint32 coins_model = 0;
	if(valConfig.isMember("coins_model"))
		coins_model = valConfig["coins_model"].asUInt();
	
	uint32 init_coins = 0;
	if(valConfig.isMember("init_coins"))
		init_coins = valConfig["init_coins"].asUInt();
	
	uint32 think_time = 0;
	if(valConfig.isMember("think_time"))
		think_time = valConfig["think_time"].asUInt();
	
	uint32 timeout = 0;
	if(valConfig.isMember("timeout"))
		timeout = valConfig["timeout"].asUInt();
	
	String extra_data = "";
	if(valConfig.isMember("extra_data"))
		extra_data = valConfig["extra_data"].asString();
	
	String battle_name = "";
	if(valConfig.isMember("battle_name"))
		battle_name = valConfig["battle_name"].asString();
	
	stPlayerCreateCenterBattle stPCB;
	stPCB.name = pUser->getStringField("nick");
	stPCB.gz_id = gz_id;					// 分区ID
	stPCB.game_id = game_id;				// 游戏ID
	stPCB.base_coins = base_coins;			// 底分
	stPCB.fan_coins = fan_coins;			// 翻分
	stPCB.limit_loop = limit_loop;			// 限制局数
	stPCB.limit_time = limit_time;			// 限制时间
	stPCB.top_times = top_times;			// 限制倍数翻数
	stPCB.coins_model = coins_model;		// 输赢游戏货币类型
	stPCB.init_coins = init_coins;			// 初始带入游戏币数量
	stPCB.think_time = think_time;			// 考虑时间
	stPCB.timeout = timeout;				// 超时时间
	stPCB.extra_data = extra_data;			// 游戏玩法
	stPCB.mode = mode;						// 游戏模式
	
	stPCB.battle_name = ServerDatabase.EscapeString(battle_name);	// 房间名称
	
	CenterBattle cb;
	uint8 result = enResult_Sucess;
	do
	{
		bool isInHuoDong = false;
		uint32 time_zero = time(0);
		std::list<CenterBattle> lstData;
		uint32 playing_count = GetCenterBattleList(&lstData, "pid = %u and status < 255",pUser->getUInt32Field("platform_id"));
		if(playing_count >= sXmlDataMgr.GetConfXMLValue("MAX_CENTER_BATTLE_COUNT"))
		{// 创建牌局数量超过限制
			result = enCreateBattle_OverLimitCount;
			break;
		}
		
		stCenterBattleMode stMode = sXmlDataMgr.GetCenterBattleModeByGameid(stPCB.game_id, stPCB.mode);
		if(!stMode.game_id)
		{// 游戏玩法判断
			result = enCreateBattle_NoThisMode;
			break;
		}
		
		uint32 value = stPCB.limit_loop;
		uint32 agent_id = pUser->getUInt32Field("reg_from");
		
		stCenterBattleOpenCoins stCBOC = sXmlDataMgr.GetCenterBattleOpenCoins(agent_id, game_id, 1024, 0, value, mode);
		if(stCBOC.model_id == 0)
		{// 错误的配置
			result = enCreateBattle_ErrorLoop;
			break;
		}
		
		if(club_id || club_room_id)
		{// 检测创建者权限和创建上限
			CenterClub cc;
			if(!sCenterClubMgr.GetCenterClub(club_id, &cc))
			{// 无效的俱乐部ID
				result = enCreateBattle_NoClubID;
				break;
			}
			
			if(!stCBOC.use_club_diamand)
			{// 不扣公会资费的扣玩家的钱
				if(!sCenterClubMemberMgr.IsPlayerClubManager(club_id, pUser->getUInt32Field("platform_id")))				
				{// 权限不足
					result = enCreateBattle_ClubQuanXian;
					break;
				}
			}
		}
		
		if(stPCB.limit_loop == 0 && stPCB.limit_time == 0 && pay_mode != enPayMode_LoopPay)
		{// 必须设置一个限制条件
			result = enCreateBattle_NoLimit;
			break;
		}
		
		if(stPCB.limit_loop && stPCB.limit_time)
		{// 只能选择一个限制条件
			result = enCreateBattle_JustOneLimit;
			break;
		}
		
		if(stPCB.limit_loop && stPCB.limit_loop < sXmlDataMgr.GetConfXMLValue("CENTER_BATTLE_LEAST_COUNT"))
		{// 最少局数限制
			result = enCreateBattle_NeedMoreLoop;
			break;
		}
		
		if(stPCB.limit_time && stPCB.limit_time < sXmlDataMgr.GetConfXMLValue("CENTER_BATTLE_LEAST_TIME"))
		{// 最少时间限制
			result = enCreateBattle_NeedMoreTime;
			break;
		}
		
		if(stPCB.base_coins < sXmlDataMgr.GetConfXMLValue("CENTER_BATTLE_LEAST_BASECOINS"))
		{// 错误的底分
			result = enCreateBattle_ErrorBaseCoins;
			break;
		}
		
		if(time_zero >= stCBOC.free_begin_time && time_zero <= stCBOC.free_end_time)
		{// 免费
			isInHuoDong = true;
		}
		else
		{// 不免费
			if(pay_mode == enPayMode_FangZhu)
			{// 房主付费模式
				if(!sGLMgr.reduceItemNum(pChr, stCBOC.model_id, stCBOC.num))
				{// 开局费不足
					result = enCreateBattle_GoldTicketNeed;
					break;
				}
			}
		}
		
		if(club_id && stCBOC.use_club_diamand)
			cb.pid = sCenterClubMgr.GetClubCreaterPid(club_id);	// pid
		else
			cb.pid = pUser->getUInt32Field("platform_id");		// pid
		
		cb.reg_from = pUser->getUInt32Field("reg_from");	// reg_from
		cb.openid = pUser->getStringField("sdata1");		// openid
		
		cb.status = enBattleStatus_Require;		// 申请组局
		cb.gz_id = stPCB.gz_id;
		cb.game_id = stPCB.game_id;
		cb.base_coins = stPCB.base_coins;
		cb.fan_coins = stPCB.fan_coins;
		cb.limit_loop = stPCB.limit_loop;
		cb.istrack = stPCB.istrack;
		cb.limit_time = stPCB.limit_time;
		cb.top_times = stPCB.top_times;
		cb.coins_model = stPCB.coins_model;
		cb.init_coins = stPCB.init_coins;
		cb.think_time = stPCB.think_time;
		cb.timeout = stPCB.timeout;
		cb.pause = false;
		cb.start_time = time(0);
		cb.create_time = sGLMgr.GetCurDateTime();	// 创建时间
		cb.battle_name = stPCB.battle_name;		// 房间名称
		cb.sdata2 = stPCB.extra_data;			// 游戏玩法
		cb.mode = stPCB.mode % 100;				// 游戏模式
		
		cb.name = pChr->getStringField("name");	// 房主昵称
		cb.head = pChr->getStringField("desc");	// 房主头像
		cb.update_key = 1;						// 数据更新锁
		if(!isInHuoDong)
		{// 没有免费活动
			cb.data1 = stCBOC.model_id;				// 开局费类型
			if(pay_mode == enPayMode_FangZhu)
				cb.data2 = stCBOC.num;				// 开局费数量
			else if(pay_mode == enPayMode_AAPay)
				cb.data2 = stCBOC.aa_num;			// AA值付费数量
		}
		
		if(cb.pay_mode == enPayMode_FangZhu)
		{// 记录房主扣费
			Json::Value valPlayer, valPay;
			if(club_id && stCBOC.use_club_diamand)
			{
				uint32 club_creater_pid = sCenterClubMgr.GetClubCreaterPid(club_id);
				uint32 club_creater_cid = 0;
				std::list<ResourcePtr> users;
				sUserMgr.getDBObjects(&users, 0, 1, "platform_id = %u and gz_id = %u ", club_creater_pid, pUser->getUInt32Field("gz_id"));
				if(users.size())
					club_creater_cid = (*users.begin())->getUInt32Field("char_id");
				
				valPlayer["pid"] = club_creater_pid;
				valPlayer["cid"] = club_creater_cid;
				valPlayer["gz_id"] = uint32(pUser->getUInt32Field("gz_id"));
			}
			else
			{
				valPlayer["pid"] = pUser->getUInt32Field("platform_id");
				valPlayer["cid"] = uint32(pChr->getHandle());
				valPlayer["gz_id"] = uint32(pChr->getUInt32Field("gz_id"));
			}
			valPlayer["model_id"] = cb.data1;
			valPlayer["num"] = cb.data2;
			
			valPay[0] = valPlayer;
			
			Json::FastWriter w;
			cb.sdata4 = w.write(valPay);
		}
		
		if(!AddCenterBattle(cb))
		{// 创建数据失败
			result = enCreateBattle_CreateDataField;
			
			if(pay_mode == enPayMode_FangZhu)	// 返还上面已经扣除的金卷
				sGLMgr.addItemNum(pChr, stCBOC.model_id, cb.data2);
			break;
		}
		
	}
	while(0);
	
	Log.Debug("CenterBattleManager::RobotCreateCenterBattle","player pid[%u] result[%d] time_now[%u]", pUser->getUInt32Field("platform_id"), result, now());
	
	// 发送创建组局结果（结果是成功 表示道指定分区服务器申请创建牌桌）
	WorldPacket packet;
	if(sProtocolsMgr.CreateRequireCenterBattleResultPacket(&packet, result))
		sGLMgr.SendProtocolsToChr(pChr,&packet);
	
	if(result != enResult_Sucess)
		return result;
	
	if(result == enResult_Sucess)
	{// 发送组局列表
		if(sProtocolsMgr.CreateCenterBattleInfoPacket(&packet, cb))
			sGLMgr.SendProtocolsToChr(pChr,&packet);
		
		// 记录创建日志
		sLogDataMgr.CreateCenterBattleLog(cb.pid, cb.cb_id, cb.game_id, cb.gz_id, cb.data1, cb.data2, enCenterBattleReturnGold_CreateSucess, cb.curr_loop, cb.curr_loop == cb.limit_loop, cb.mode);
		// 记录用户习惯
		Json::Value valCopy;
		valCopy["gz_id"] = stPCB.gz_id;							// 分区ID
		valCopy["game_id"] = stPCB.game_id;						// 游戏ID
		valCopy["base_coins"] = stPCB.base_coins;				// 底分
		valCopy["fan_coins"] = stPCB.fan_coins;					// 翻分
		valCopy["istrack"] = stPCB.istrack;						// 跟踪（未用）
		valCopy["limit_loop"] = stPCB.limit_loop;				// 限制轮次
		valCopy["limit_time"] = stPCB.limit_time;				// 限制时间（未用）
		valCopy["top_times"] = stPCB.top_times;					// 封顶
		valCopy["coins_model"] = stPCB.coins_model;				// 初始带入的货币类型（未用）
		valCopy["init_coins"] = stPCB.init_coins;				// 初始带入的货币数量（未用）
		valCopy["think_time"] = stPCB.think_time;				// 思考时间（未用）
		valCopy["timeout"] = stPCB.timeout;						// 牌桌超时时间（未用）
		valCopy["battle_name"] = stPCB.battle_name;				// 房间名称
		valCopy["extra_data"] = stPCB.extra_data;				// 玩法附加数据
		valCopy["mode"] = cb.mode;								// 游戏玩法
		valCopy["pid"] = uint32(pUser->getUInt32Field("platform_id"));	// 用户PID
		
		Json::FastWriter w;
		String strConfig = w.write(valCopy);
		strExtraData =strConfig;
		
		sCRUserConfigMgr.AddCenterBattleConfig(strConfig);
		
		// 网关创建牌桌
		Json::Value valUrl;
		valUrl["gz_id"] = stPCB.gz_id;
		valUrl["pid"] = uint32(pUser->getUInt32Field("platform_id"));
		valUrl["cb_id"] = uint32(cb.cb_id);
		valUrl["platform"] = strPlatform;
		valUrl["agent_id"] = uint32(pUser->getUInt32Field("reg_from"));
		
		sGLMgr.SendCreateChannelGateway(pChr, w.write(valUrl), strExtraData, strShareInfo);
	}
	
	return enResult_Sucess;
}

// 系统帮玩家创建组局
uint8 CenterBattleManager::SystemCreateCenterBattle(String strData)
{
	if(strData == "")
		return enCreateBattle_EmprtParmas;
	
	Json::Value val;
	Json::Reader reader;
	reader.parse(strData, val);
	
	uint32 gz_id = 0;
	uint32 mode = 0;
	uint32 game_id = 0;
	
	if(val.isMember("gz_id"))
		gz_id = val["gz_id"].asUInt();
	
	if(val.isMember("mode_id"))
		mode = val["mode_id"].asUInt();
	
	if(val.isMember("game_id"))
		game_id = val["game_id"].asUInt();
	
	Log.Debug("CenterBattleManager::SystemCreateCenterBattle","gz_id[%u] game_id[%u] 111", gz_id, game_id);
	
WGS_CENTERBATTLE_LOCK
	
	if(game_id == 0)
		return enCreateBattle_NoGzidInfo;
	Log.Debug("CenterBattleManager::SystemCreateCenterBattle","gz_id[%u] game_id[%u] 222", gz_id, game_id);
	Json::Value valConfig;
	reader.parse(strData, valConfig);
	
	uint32 base_coins = 0;
	if(valConfig.isMember("base_coins"))
		base_coins = valConfig["base_coins"].asUInt();
	
	uint32 fan_coins = 0;
	if(valConfig.isMember("fan_coins"))
		fan_coins = valConfig["fan_coins"].asUInt();
	
	// uint32 pay_mode = 0;		// 付费模式（1 房主全额 2 AA制）
	// if(valConfig.isMember("pay_mode"))
		// pay_mode = valConfig["pay_mode"].asUInt();
	
	uint32 limit_loop = 0;
	if(valConfig.isMember("limit_loop"))
		limit_loop = valConfig["limit_loop"].asUInt();
	
	if(valConfig.isMember("round_num"))
		limit_loop = valConfig["round_num"].asUInt();
	
	uint32 limit_time = 0;
	if(valConfig.isMember("limit_time"))
		limit_time = valConfig["limit_time"].asUInt();
	
	// uint32 club_id = 0;
	// if(valConfig.isMember("club_id"))
		// club_id = valConfig["club_id"].asUInt();
	
	// uint32 club_room_id = 0;
	// if(valConfig.isMember("club_room_id"))
		// club_room_id = valConfig["club_room_id"].asUInt();
	
	uint32 top_times = 0;
	if(valConfig.isMember("top_times"))
		top_times = valConfig["top_times"].asUInt();
	
	uint32 coins_model = 0;
	if(valConfig.isMember("coins_model"))
		coins_model = valConfig["coins_model"].asUInt();
	
	uint32 init_coins = 0;
	if(valConfig.isMember("init_coins"))
		init_coins = valConfig["init_coins"].asUInt();
	
	uint32 think_time = 0;
	if(valConfig.isMember("think_time"))
		think_time = valConfig["think_time"].asUInt();
	
	uint32 timeout = 0;
	if(valConfig.isMember("timeout"))
		timeout = valConfig["timeout"].asUInt();
	
	uint32 agent_id = 0;
	if(valConfig.isMember("agent_id"))
		agent_id = valConfig["agent_id"].asUInt();
	
	String extra_data = "";
	if(valConfig.isMember("extra_data"))
		extra_data = valConfig["extra_data"].asString();
	
	String battle_name = "";
	if(valConfig.isMember("battle_name"))
		battle_name = valConfig["battle_name"].asString();
	
	stPlayerCreateCenterBattle stPCB;
	stPCB.gz_id = gz_id;					// 分区ID
	stPCB.game_id = game_id;				// 游戏ID
	stPCB.base_coins = base_coins;			// 底分
	stPCB.fan_coins = fan_coins;			// 翻分
	stPCB.limit_loop = limit_loop;			// 限制局数
	stPCB.limit_time = limit_time;			// 限制时间
	stPCB.top_times = top_times;			// 限制倍数翻数
	stPCB.coins_model = coins_model;		// 输赢游戏货币类型
	stPCB.init_coins = init_coins;			// 初始带入游戏币数量
	stPCB.think_time = think_time;			// 考虑时间
	stPCB.timeout = timeout;				// 超时时间
	stPCB.extra_data = extra_data;			// 游戏玩法
	stPCB.mode = mode;						// 游戏模式
	
	stPCB.battle_name = ServerDatabase.EscapeString(battle_name);	// 房间名称
	
	CenterBattle cb;
	uint8 result = enResult_Sucess;
	do
	{
		Log.Debug("CenterBattleManager::SystemCreateCenterBattle","mode[%u] game_id[%u] 333", stPCB.mode, stPCB.game_id);
		stCenterBattleMode stMode = sXmlDataMgr.GetCenterBattleModeByGameid(stPCB.game_id, stPCB.mode);
		if(!stMode.game_id)
		{// 游戏玩法判断
			result = enCreateBattle_NoThisMode;
			break;
		}
		
		uint32 value = stPCB.limit_loop;
		Log.Debug("CenterBattleManager::SystemCreateCenterBattle","gz_id[%u] game_id[%u] 444", gz_id, game_id);
		stCenterBattleOpenCoins stCBOC = sXmlDataMgr.GetCenterBattleOpenCoins(agent_id, game_id, 1000, 0, value, mode);
		if(stCBOC.model_id == 0)
		{// 错误的配置
			result = enCreateBattle_ErrorLoop;
			break;
		}
		
		cb.reg_from = agent_id;								// reg_from
		
		cb.status = enBattleStatus_Require;		// 申请组局
		cb.gz_id = stPCB.gz_id;
		cb.game_id = stPCB.game_id;
		cb.base_coins = stPCB.base_coins;
		cb.fan_coins = stPCB.fan_coins;
		cb.limit_loop = stPCB.limit_loop;
		cb.istrack = stPCB.istrack;
		cb.limit_time = stPCB.limit_time;
		cb.top_times = stPCB.top_times;
		cb.coins_model = stPCB.coins_model;
		cb.init_coins = stPCB.init_coins;
		cb.think_time = stPCB.think_time;
		cb.timeout = stPCB.timeout;
		cb.pause = false;
		cb.start_time = time(0);
		cb.create_time = sGLMgr.GetCurDateTime();	// 创建时间
		cb.battle_name = stPCB.battle_name;			// 房间名称
		cb.sdata2 = stPCB.extra_data;				// 游戏玩法
		cb.mode = stPCB.mode;						// 游戏模式
		cb.update_key = 1;							// 数据更新锁
		Log.Debug("CenterBattleManager::SystemCreateCenterBattle","gz_id[%u] game_id[%u] 555", gz_id, game_id);
		/* if(!AddCenterBattle(cb))
		{// 创建数据失败
			result = enCreateBattle_CreateDataField;
			break;
		} */
	}
	while(0);
	
	Log.Debug("CenterBattleManager::SystemCreateCenterBattle","gz_id[%u] game_id[%u] 666", gz_id, game_id);
	// 发送创建组局结果（结果是成功 表示道指定分区服务器申请创建牌桌）
	if(result != enResult_Sucess)
		return result;
	
	if(result == enResult_Sucess)
	{
		Log.Debug("CenterBattleManager::SystemCreateCenterBattle","gz_id[%u] game_id[%u] 777", gz_id, game_id);
		// 网关创建牌桌
		Json::FastWriter w;
		// valConfig["pid"] = 0;
		// valConfig["cb_id"] = uint32(cb.cb_id);
		
		sGLMgr.SendSystemCreateChannelGateway(w.write(valConfig));
	}
	
	return enResult_Sucess;
}

// 创建游戏牌桌
bool CenterBattleManager::CreateGameChannel(WSSocketPtr & socket, const uint32 & pid, const uint32 & cb_id, const uint32 & gz_id, const uint32 & update_key)
{
	if(!pid || !cb_id || socket.isNull())
		return false;
	
	CenterBattle cb;
	uint8 result = enResult_Sucess;
	stPlayerCreateCenterBattle stPCB;
	
	do
	{
		{
			WGS_CENTERBATTLE_LOCK
			if(!GetCenterBattle(cb_id, &cb))
			{// 未找到指定组局信息
				result = enCreateGameBattle_NoThisCenterBattle;
				break;
			}
		}
		
		// if(pid != cb.pid)
		// {// 错误的pid
			// result = enCreateGameBattle_ErrorPID;
			// break;
		// }
		
		if(cb.status != enBattleStatus_Require)
		{// 错误的状态
			result = enCreateGameBattle_ErrorStatus;
			break;
		}
		
		stPCB.cb_id = cb.cb_id;
		stPCB.pid = cb.pid;
		stPCB.gz_id = cb.gz_id;
		stPCB.game_id = cb.game_id;
		stPCB.base_coins = cb.base_coins;
		stPCB.fan_coins = cb.fan_coins;
		
		stPCB.mode = cb.mode;
		stPCB.istrack = cb.istrack;
		stPCB.limit_loop = cb.limit_loop;
		stPCB.limit_time = cb.limit_time;
		stPCB.top_times = cb.top_times;
		
		stPCB.coins_model = cb.coins_model;
		stPCB.init_coins = cb.init_coins;
		
		stPCB.think_time = cb.think_time;
		stPCB.timeout = cb.timeout;
		
		stPCB.name = cb.name;
		stPCB.battle_name = cb.battle_name;
		stPCB.extra_data = cb.sdata2;
		
		ChannelPtr pChannel = sGLMgr.CreateCenterChannel(stPCB);
		if(pChannel.isNull())
		{// 创建牌桌失败
			result = enCreateGameBattle_CreateFailed;
			break;
		}
		
		cb.status = enBattleStatus_Process;					// 更新状态
		cb.join_code = pChannel->getStringField("winner");	// 进入码
		cb.channel_id = pChannel->getHandle();				// 牌桌ID
		
	using namespace AIScript;
		AIChannelBaseInterface * pChnAi = TO_CHANNEL_BASE_INTERFACE(pChannel->getAIInterface());
		if(!pChnAi)
		{
			result = enCreateGameBattle_CreateFailed;
			break;
		}
		
		cb.max_player = pChnAi->GetMaxPlayerNum();
		{
			WGS_CENTERBATTLE_LOCK
			if(!UpdateCenterBattle(cb, update_key))
			{// 数据更新失败（有可能是重复进行操作导致）
				result = enCreateGameBattle_DataUpdateFailed;
				break;
			}
		}
		
		if(cb.club_id)
		{// 玩家【%s】在%s创建了牌桌，消耗%u钻石
			char buf[256] = "";
			sprintf(buf, sMsg.getMessage("club_createbattle_message").c_str(), cb.name.c_str(), sGLMgr.GetCurDateTime().c_str(), cb.data2);
			
			String strMessage = buf;
			sCenterClubMessageMgr.AddSystemChatMessage(strMessage, cb.reg_from, cb.club_id);
		}
		
	}while(0);
	
	Log.Debug("CenterBattleManager::CreateGameChannel","pid[%u] result[%u] cb_id[%u] time_now[%u]", pid, result, cb.cb_id, now());
	
	// 发送结果
	String join_code = cb.join_code;
	WorldPacket packet;
	if(sProtocolsMgr.CreateGameBattleResultPacket(&packet, cb.cb_id, join_code, result))
		socket->SendPacket(&packet);
	if(sProtocolsMgr.CreateCenterBattleInfoPacket(&packet, cb))
		socket->SendPacket(&packet);
	return true;
}

// 机器人帮玩家创建组局
uint8 CenterBattleManager::RobotCreateGameChannel(String strParmars)
{
	if(strParmars == "")
		return enResult_Failed;
	
	CenterBattle cb;
	uint8 result = enResult_Sucess;
	
	Json::Value val;
	Json::Reader reader;
	reader.parse(strParmars, val);
	
	uint32 cb_id = 0;
	if(val.isMember("cb_id"))
		cb_id = val["cb_id"].asUInt();
	
	uint32 pid = 0;
	if(val.isMember("pid"))
		pid = val["pid"].asUInt();
	
	if(!cb_id || !pid)
		return enResult_Failed;
	
	stPlayerCreateCenterBattle stPCB;
	do
	{
		{
			WGS_CENTERBATTLE_LOCK
			if(!GetCenterBattle(cb_id, &cb))
			{// 未找到指定组局信息
				result = enCreateGameBattle_NoThisCenterBattle;
				break;
			}
		}
		
		// if(pid != cb.pid)
		// {// 错误的pid
			// result = enCreateGameBattle_ErrorPID;
			// break;
		// }
		
		if(cb.status != enBattleStatus_Require)
		{// 错误的状态
			result = enCreateGameBattle_ErrorStatus;
			break;
		}
		
		stPCB.cb_id = cb.cb_id;
		stPCB.pid = cb.pid;
		stPCB.gz_id = cb.gz_id;
		stPCB.game_id = cb.game_id;
		stPCB.base_coins = cb.base_coins;
		stPCB.fan_coins = cb.fan_coins;
		
		stPCB.mode = cb.mode;
		stPCB.istrack = cb.istrack;
		stPCB.limit_loop = cb.limit_loop;
		stPCB.limit_time = cb.limit_time;
		stPCB.top_times = cb.top_times;
		
		stPCB.coins_model = cb.coins_model;
		stPCB.init_coins = cb.init_coins;
		
		stPCB.think_time = cb.think_time;
		stPCB.timeout = cb.timeout;
		
		stPCB.name = cb.name;
		stPCB.battle_name = cb.battle_name;
		stPCB.extra_data = cb.sdata2;
		
		Log.Debug("CenterBattleManager::CreateGameChannel","pid[%u] cb_id[%u] time_now[%u] 555", pid, cb_id, now());
		ChannelPtr pChannel = sGLMgr.CreateCenterChannel(stPCB);
		if(pChannel.isNull())
		{// 创建牌桌失败
			result = enCreateGameBattle_CreateFailed;
			break;
		}
		
		cb.status = enBattleStatus_Process;					// 更新状态
		cb.join_code = pChannel->getStringField("winner");	// 进入码
		cb.channel_id = pChannel->getHandle();				// 牌桌ID
		
		Log.Debug("CenterBattleManager::CreateGameChannel","pid[%u] cb_id[%u] time_now[%u] 666", pid, cb_id, now());
	using namespace AIScript;
		
		AIChannelBaseInterface * pChnAi = TO_CHANNEL_BASE_INTERFACE(pChannel->getAIInterface());
		if(!pChnAi)
		{
			result = enCreateGameBattle_CreateFailed;
			break;
		}
		
		cb.max_player = pChnAi->GetMaxPlayerNum();
		Log.Debug("CenterBattleManager::CreateGameChannel","pid[%u] cb_id[%u] time_now[%u] 777", pid, cb_id, now());
		
		{
			WGS_CENTERBATTLE_LOCK
			if(!UpdateCenterBattle(cb, 0))
			{// 数据更新失败（有可能是重复进行操作导致）
				result = enCreateGameBattle_DataUpdateFailed;
				break;
			}
		}
		
		if(cb.club_id)
		{// 玩家【%s】在%s创建了牌桌，消耗%u钻石
			char buf[256] = "";
			sprintf(buf, sMsg.getMessage("club_createbattle_message").c_str(), cb.name.c_str(), sGLMgr.GetCurDateTime().c_str(), cb.data2);
			
			String strMessage = buf;
			sCenterClubMessageMgr.AddSystemChatMessage(strMessage, cb.reg_from, cb.club_id);
		}
		
	}while(0);
	
	Log.Debug("CenterBattleManager::CreateGameChannel","pid[%u] result[%u] cb_id[%u] time_now[%u]", pid, result, cb.cb_id, now());
	return result;
}

// 牌桌创建更新组局信息（更新状态，牌桌ID，进入牌桌的兑换码）
bool CenterBattleManager::UpdateCenterBattleChannelInfo(CharPtr & pChr, const uint32 & cb_id, ChannelPtr & pChannel)
{
	if(pChr.isNull() || pChannel.isNull())
		return false;
	
WGS_CENTERBATTLE_LOCK
	UserPtr pUser = sUserMgr.getByHandle(pChr->getUInt32Field("userid"));
	if(pUser.isNull())
	{
		pUser = sUserMgr.load(pChr->getUInt32Field("userid"));
		if(pUser.isNull())
			return false;
	}
	
	CenterBattle cb;
	if(!GetCenterBattle(cb_id, &cb))
		return false;
	
	// 错误状态
	if(cb.status != enBattleStatus_Created)
		return false;
	
	// pid不对
	if(cb.pid != pUser->getUInt32Field("platform_id"))
		return false;
	
	cb.status = enBattleStatus_Process;
	cb.channel_id = pChannel->getHandle();
	
	Json::Reader reader;
	Json::Value val;
	reader.parse(pChannel->getStringField("info"), val);
	
	if(val.isMember("join_code"))
	{// 设置登陆验证码
		cb.join_code = val["join_code"].asString();
	}
	
	// 更新数据
	UpdateCenterBattle(cb);
	
	// 发送更新协议
	WorldPacket packet;
	if(sProtocolsMgr.CreateCenterBattleInfoPacket(&packet, cb))
		sGLMgr.SendProtocolsToChr(pChr,&packet);
	
	return true;
}

void CenterBattleManager::SendPlayerCenterBattleListInfo(CharPtr & pChr)
{
	if(pChr.isNull())
		return ;
	
WGS_CENTERBATTLE_LOCK
	UserPtr pUser = sUserMgr.getByHandle(pChr->getUInt32Field("userid"));
	if(pUser.isNull())
		return ;
	
	// 加上玩家进入的记录
	uint32 pid = pUser->getUInt32Field("platform_id");
	
	std::list<CenterBattle> lstData;
	GetCenterBattleList(&lstData, "status < 255 and pid = %u order by start_time desc limit %u", pid, sXmlDataMgr.GetConfXMLValue("CENTER_BATTLEINFO_MAXNUM"));
	
	WorldPacket packet;
	if(sProtocolsMgr.CreateCenterBattleListPacket(&packet, lstData))
		sGLMgr.SendProtocolsToChr(pChr, &packet);
}

// 发送某个俱乐部组局信息列表
void CenterBattleManager::SendClubCenterBattleListInfo(CharPtr & pChr, const uint64 & club_id)
{
	if(pChr.isNull())
		return ;
	
WGS_CENTERBATTLE_LOCK
	std::list<CenterBattle> lstData;
	GetCenterBattleList(&lstData, "status < 255 and club_id = %u order by start_time desc", club_id);
	
	WorldPacket packet;
	if(sProtocolsMgr.CreateCenterBattleListPacket(&packet, lstData))
		sGLMgr.SendProtocolsToChr(pChr, &packet);
}

// 发送某个组局信息
void CenterBattleManager::SendPlayerCenterBattleInfo(CharPtr & pChr, const uint32 & cb_id)
{
	if(pChr.isNull())
		return ;
	
	CenterBattle cb;
	if(!GetCenterBattle(cb_id, &cb))
		return ;
	
	WorldPacket packet;
	if(sProtocolsMgr.CreateCenterBattleInfoPacket(&packet, cb))
		sGLMgr.SendProtocolsToChr(pChr, &packet);
}

// 暂停/继续组局（该功能屏蔽掉）
bool CenterBattleManager::OperatorBattle(WSSocketPtr socket, 
										const uint32 & platform_id, 
										const uint32 & cb_id, 
										const uint8 & mode, 
										const uint32 & data,
										const uint32 & update_key)
{
	if(!cb_id)
		return false;
	
	using namespace AIScript;
	
	uint8 result = enResult_Sucess;
	AIChannelBaseInterface * pCII = NULL;
	CenterBattle cb;
	
	Log.Debug("CenterBattleManager::OperatorBattle","platform_id[%u] cb_id[%u] mode[%u] data[%u]", platform_id, cb_id, mode, data);
	do
	{
		{
			WGS_CENTERBATTLE_LOCK
			if(!GetCenterBattle(cb_id, &cb))
			{// 无此组局
				result = enPauseBattle_NoThisCenterBattle;
				break;
			}
		}
		
		// 先屏蔽
		if(cb.club_id)
		{// 俱乐部，管理员都可以解散
			if(!sCenterClubMemberMgr.IsPlayerClubManager(cb.club_id, platform_id) && cb.pid != platform_id)
			{
				result = enPauseBattle_ErrorPID;
				break;
			}
		}
		else
		{// 自己创建的要自己解散
			if(cb.pid != platform_id)
			{
				result = enPauseBattle_ErrorPID;
				break;
			}
		}
		
		if(cb.channel_id == 0)
		{// 没有channel
			result = enPauseBattle_ChannelNull;
			break;
		}
		
		if(sXmlDataMgr.IsInGameIds(cb.game_id))
		{// 在游戏服务器解散
			ChannelPtr pChannel = sChannelMgr.getByHandle(cb.channel_id);
			if(pChannel.isNull())
			{// 没有channel
				result = enPauseBattle_ChannelNull;
				break;
			}
			
			pCII = TO_CHANNEL_BASE_INTERFACE(pChannel->getAIInterface());
			if(!pCII)
			{
				result = enPauseBattle_ChannelNull;
				break;
			}
			
			bool bPause = pCII->GetPauseStatus();
			if(bPause && mode == enCenterBattlePauseStatus_Pause)
			{// 原来是暂停的
				result = enPauseBattle_SameOperator;
				break;
			}
			else if(!bPause && mode == enCenterBattlePauseStatus_CancelPause)
			{// 原来是运行的
				result = enPauseBattle_SameOperator;
				break;
			}
			else if(mode == enCenterBattlePauseStatus_KickPlayer)
			{// 踢人
				return false;
				
				// 牌桌踢人结果
				if(!pCII->KickPlayer(data))
				{
					result = enKickPlayer_KickFailed;
					break;
				}
			}
			else if(mode == enCenterBattlePauseStatus_Dissolve)
			{// 解散牌桌
				// 不和游戏在同一个服务器，调用网关，在同一个服务器调用解散接口
				if(!pCII->DissolveChannel())
				{// 解散失败
					result = enKickPlayer_DissolveFailed;
					break;
				}
			}
		}
		else
		{// 在棋牌圈解散
			// 调用网关指令
			
			Json::Value val;
			val["channel_id"] = cb.channel_id;
			val["gz_id"] = cb.gz_id;
			val["op_mode"] = mode;
			val["data"] = data;
			val["agent_id"] = 0;
			
			Json::FastWriter w;
			String strData = w.write(val);
			
			Log.Debug("CenterBattleManager::OperatorBattle","strData[%s]", strData.c_str());
			result = sGLMgr.SendOpCenterBattleGateway(strData);
		}
		
	}while(0);
	
	// 发送结果
	if(result == enResult_Sucess)
	{
		bool bWrite = false;
		// 设置牌桌暂停
		if(mode == enCenterBattlePauseStatus_Pause)
		{
			pCII->Pause();
			cb.pause = 1;
			bWrite = true;
		}
		else if(mode == enCenterBattlePauseStatus_CancelPause)
		{
			pCII->CancelPause();
			cb.pause = 0;
			bWrite = true;
		}
		else if(mode == enCenterBattlePauseStatus_KickPlayer)
		{// 踢人
			Json::Reader reader;
			Json::Value val,newVal, blackVal;
			reader.parse(cb.player, val);
			reader.parse(cb.black_list, blackVal);
			
			for (Json::Value::iterator iterVal=val.begin(); iterVal!=val.end(); ++iterVal)
			{
				uint32 char_id = (*iterVal)["cid"].asUInt();
				if(char_id == data)
				{// 不拷贝要踢出得玩家数据
					bWrite = true;
					blackVal[iterVal.key().asString()]["pid"] = (*iterVal)["pid"];
					blackVal[iterVal.key().asString()]["cid"] = (*iterVal)["cid"];
					continue;
				}
				
				CharPtr pChr = sCharMgr.getByHandle(char_id);
				if(pChr.isNull())
				{
					pChr = sCharMgr.load(char_id);
					if(pChr.isNull())
						continue;
				}
				
				UserPtr pUserPtr = sUserMgr.getByHandle(pChr->getUInt32Field("userid"));
				if(pUserPtr.isNull())
				{
					pUserPtr = sUserMgr.load(pChr->getUInt32Field("userid"));
					if(pUserPtr.isNull())
						continue;
				}
				
				newVal[iterVal.key().asString()]["pid"] = pUserPtr->getUInt32Field("platform_id");
				newVal[iterVal.key().asString()]["cid"] = char_id;
				newVal[iterVal.key().asString()]["name"] = (*iterVal)["name"];
				newVal[iterVal.key().asString()]["desc"] = (*iterVal)["desc"];
			}
			
			if(bWrite)
			{
				Json::FastWriter w;
				// 将踢出去的人加入到黑名单
				cb.black_list = w.write(blackVal);
				cb.player = w.write(newVal);
			}
		}
		
		if(bWrite)
		{
			{
				WGS_CENTERBATTLE_LOCK
				if(!UpdateCenterBattle(cb, update_key))
				{
					result = enKickPlayer_DataUpdateFailed;
				}
				else
				{// 数据更新成功 发送更新后的信息
					WorldPacket packet;
					if(!socket.isNull() && sProtocolsMgr.CreateCenterBattleInfoPacket(&packet, cb))
						socket->SendPacket(&packet);
				}
			}
		}
	}
	
	WorldPacket packet;
	if(sProtocolsMgr.CreateCenterBattleOpPacket(&packet, mode, cb.cb_id, data, result))
		socket->SendPacket(&packet);
	
	return true;
}

// 踢人
bool CenterBattleManager::KickPlayer(WSSocketPtr socket, const uint32 & platform_id, const uint32 & cb_id, const uint32 & kick_charid)
{
	// 该函数没有调用了
	return true;
}

// 进牌桌（框架部分只需要将玩家丢入牌桌，由牌桌自身来处理坐座位的逻辑）
bool CenterBattleManager::JoinCenterBattle(CharPtr & pChr, String join_code)
{
	if(pChr.isNull())
		return false;
	
	UserPtr pUser = sUserMgr.getByHandle(pChr->getUInt32Field("userid"));
	if(pUser.isNull())
		return false;
	
	uint32 pid = pUser->getUInt32Field("platform_id");
	uint32 agent_id = pUser->getUInt32Field("reg_from");
	using namespace AIScript;
	
	std::vector<String> vStr = StringUtil::split(join_code, ",");
	if(vStr.empty())
		return false;
	
	String str_joinCode = vStr[0];
	
	uint32 cb_id = 0;
	if(vStr.size() > 1)
	{// 组局ID
		cb_id = StringConverter::parseUnsignedInt(vStr[1]);
	}
	
	uint32 pos = 255;
	if(vStr.size() > 2)
	{// 座位号
		pos = StringConverter::parseUnsignedInt(vStr[2]);
	}
	
	String passwd = "";
	if(vStr.size() > 3)
	{// 自己设置的密码
		passwd = vStr[3];
	}
	
	uint8 result = enResult_Sucess;
	CenterBattle cb;
	
	AIChannelBaseInterface * pCII = NULL;
	AICreatureBaseInterface * pAiChrInfe = NULL;
	ChannelPtr pJoinChannel;
	
	bool bPlaying = false;
	
	TownPtr pJoinTown;
	do
	{
		pAiChrInfe = TO_CREATURE_BASE_INTERFACE(pChr->getAIInterface());
		if(!pAiChrInfe)
		{// 接口获取失败
			Log.Error("CenterBattleManager::JoinCenterBattle","cb_id[%u] game_id[%u]", cb.cb_id, cb.game_id);
			result = enResult_Failed;
			break;
		}
		
		std::list<CenterBattle> lstData;
		{
		WGS_CENTERBATTLE_LOCK
			if(cb_id == 0)
			{
				GetCenterBattleList(&lstData, "join_code = '%s' and status < 255 ", str_joinCode.c_str());
			}
			else
			{
				GetCenterBattleList(&lstData, "join_code = '%s' and cb_id = %u ", str_joinCode.c_str(), cb_id);
			}
		}
		
		if(lstData.size() != 1)
		{// 牌桌不存在
			result = enJoinChannel_NoThisBattle;
			break;
		}
		
		cb = *lstData.begin();
		
		if(cb.status == 255)
		{// 请求组局已结束
			result = enJoinChannel_GameOver;
			break;
		}
		
		if(cb.club_id)
		{// 俱乐部创建的必须是俱乐部会员才可以进入
			if(!sCenterClubMemberMgr.IsPlayerInClub(cb.club_id, pid))
			{
				result = enResult_Failed;
				break;
			}
		}
		
		Json::Reader reader;
		Json::Value valData2;
		String strData2 = cb.sdata2;
		reader.parse(strData2, valData2);
		
		if(valData2.isMember("passwd"))
		{// 验证密码
			if(valData2["passwd"].asString().size())
			{
				if(passwd.compare(valData2["passwd"].asString()))
				{// 密码不正确
					result = enJoinChannel_ErrorPasswd;
					break;
				}
			}
		}
		
		bool bLocalNet = false;
		WSSocketPtr socket = pChr->getSocket();
		if(!socket.isNull())
		{
			String strIP = socket->GetIP();
			if(StringUtil::match(strIP, "192.168*"))
				bLocalNet = true;
		}
		
		if(!sXmlDataMgr.GetConfXMLValue("CHECK_SAME_AGENTID") || bLocalNet)
		{
			// goon
		}
		else
		{
			if(pUser->getUInt32Field("reg_from") != cb.reg_from)
			{// 代理商不对
				result = enJoinChannel_NoThisBattle;
				break;
			}
		}
		
		GameBank bank;
		sBankMgr.GetRealBank(pUser, bank);
		
		TownPtr pTown = pAiChrInfe->GetTown();
		if(!pTown.isNull())
		{// 在其他牌桌
			Log.Error("CenterBattleManager::JoinCenterBattle","cb_id[%u] game_id[%u] town[%u] ai[%u]", cb.cb_id, cb.game_id, pTown->getHandle(), pTown->getUInt32Field("ai"));
			if(!sXmlDataMgr.IsAIInCenterBattle(cb.game_id, pTown->getUInt32Field("ai")))
			{
				result = enJoinChannel_InOtherChannel;
				break;
			}
		}
		
		ChannelPtr pChannel = pAiChrInfe->GetChannelPtr();
		if (!pChannel.isNull())
		{// 在其他牌桌
			Log.Error("CenterBattleManager::JoinCenterBattle","cb_id[%u] game_id[%u] channel[%u] ai[%u] join_code[%s] winner[%s]", 
										cb.cb_id, cb.game_id, pChannel->getHandle(), pChannel->getUInt32Field("ai"), str_joinCode.c_str(), pChannel->getStringField("winner").c_str());
			
			if(!sXmlDataMgr.IsAIInCenterBattle(cb.game_id, pChannel->getUInt32Field("ai"))
					|| str_joinCode.compare(pChannel->getStringField("winner")))
			{
				result = enJoinChannel_InOtherChannel;
				break;
			}
		}
		
		Json::Value valP;
		reader.parse(cb.player, valP);
		
		if(pos != 255)
		{// 玩家选择坐入固定座位
			bool bSeatFull = false;
			for(Json::Value::iterator iterVal=valP.begin(); iterVal!=valP.end(); ++iterVal)
			{
				if(!(*iterVal).isMember("pos"))
					continue;
				
				if((*iterVal)["pos"].asUInt() == pos && (*iterVal)["pid"].asUInt() != pid)
				{// 座位被其他玩家占用了
					bSeatFull = true;
					break;
				}
			}
			
			if(bSeatFull)
			{
				result = enJoinChannel_SeatFull;
				break;
			}
		}
		
		bool bFindChar = false;
		for(Json::Value::iterator iterVal=valP.begin(); iterVal!=valP.end(); ++iterVal)
		{
			if(pUser->getUInt32Field("platform_id") == StringConverter::parseUnsignedInt(iterVal.key().asString()))
			{
				bFindChar = true;
				if((*iterVal)["player_status"] == enCenterBattlePlayerStatus_Playing)
				{
					bPlaying = true;
				}
				break;
			}
		}
		
		uint32 watch_playerNum = sXmlDataMgr.GetGameWatchMode(cb.reg_from, cb.game_id, cb.data1, cb.mode, cb.limit_loop);
		if(watch_playerNum == 0 || cb.data4 == 0)
		{// 没有开启观战，或者观战人数设置为0
			// 游戏开始并且人满新玩家无法进入
			if(cb.status == enBattleStatus_playing && valP.size() >= cb.max_player)
			{// 游戏中状态
				if(!bFindChar || !bPlaying)
				{// 玩家未在游戏中
					result = enJoinChannel_Playing;
					break;
				}
			}
			
			if(!bFindChar && valP.size() >= cb.max_player)
			{// 人数已满自己不在牌桌中
				result = enJoinChannel_PlayerFull;
				break;
			}
		}
		else
		{// 可以观战的时候
			if(!bFindChar && valP.size() >= cb.max_player + watch_playerNum)
			{// 算上观战人数，已满
				result = enJoinChannel_PlayerFull;
				break;
			}
		}
		
		if(valData2.isMember("max_coins"))
		{
			uint32 max_coins = valData2["max_coins"].asUInt();
			if(max_coins && max_coins < sGLMgr.GetItemNum(pChr, ItemModel_Coins))
			{// 超过最大限制铜钱
				result = enJoinChannel_NeedRoomCards;
				break;
			}
		}
		
		if(cb.status == enBattleStatus_playing && cb.data3 == 0)
		{// 游戏开始，选择了中途不能加入
			result = enJoinChannel_Playing;
			break;
		}
		
		if(cb.pay_mode == enPayMode_AAPay && !bPlaying)
		{// AA制，进入牌桌需验证是否有足够的房卡
			Json::Value valPay;
			reader.parse(cb.sdata4, valPay);
			
			bool bPayed = false;
			for(Json::Value::iterator iterVal=valPay.begin(); iterVal!=valPay.end(); ++iterVal)
			{
				uint32 pid = (*iterVal)["pid"].asUInt();
				if(pid == pUser->getUInt32Field("platform_id"))
				{
					bPayed = true;
					break;
				}
			}
			
			if(!bPayed && !bFindChar)
			{// 未支付，并且没有加入到牌桌，需要判断房费是否足够
				if(bank.status == CenterBankManager::BankStatusPrep)
				{// 钱已拷贝到银行中
					if(bank.item9 < cb.data2)
					{
						result = enJoinChannel_NeedRoomCards;
						break;
					}
				}
				else
				{// 不在目标游戏中
					if(!sXmlDataMgr.IsInGameIds(cb.game_id))
					{// 从其他游戏要往目标游戏跳转之前，验证AA费是否充足
						uint32 register_time = pUser->getUInt32Field("reg_time");
						if(register_time && register_time + 10 >= time(0))
						{// 刚好注册等待财富到账
							uint32 check_time = now();
							uint32 check_count = 0;
							bool bEoungh = false;
							
							while(check_count < 10)
							{
								if(check_time + 500 <= now())
								{
									if(sGLMgr.GetItemNum(pChr, cb.data1) < cb.data2)
									{// 未达到条件
										++check_count;
										check_time = now();
									}
									else
									{// 满足条件
										bEoungh = true;
										break;
									}
								}
							}
							
							if(!bEoungh)
							{// 确实钻石不足
								result = enJoinChannel_NeedRoomCards;
								break;
							}
						}
						else
						{// 旧账号检测
							uint32 curr_gameid = sGLMgr.GetTargetServerGameid(bank.gz_id, agent_id);
							if(curr_gameid != cb.game_id)
							{// 玩家所在服务器和目标组局服务器不在同一个服务器里
								
								if(!sXmlDataMgr.IsInGameIds(curr_gameid))
								{// 银行标记的玩家所在服务器，和登录的服务器不是同一服务器，需尝试让玩家先退出目标服务器
									Json::Value val;
									val["gz_id"] = uint32(bank.gz_id);
									val["platform_id"] = uint32(pid);
									val["agent_id"] = uint32(agent_id);
									
									Json::FastWriter w;
									if(sGLMgr.SendExitGameServerGateway(w.write(val)))
									{
										pChr->setUInt32Field("ishere", pUser->getUInt32Field("gz_id"));
										uint8 ishere = pUser->getUInt32Field("gz_id");
										
										uint16 currGZID = 0;
										sBankMgr.JoinGameServer(pUser, ishere, &currGZID);
									}
									else
									{
										result = enJoinChannel_InOtherChannel;
										break;
									}
								}
								
								// 判断房费够不够
								if(sGLMgr.GetItemNum(pChr, cb.data1) < cb.data2)
								{
									result = enJoinChannel_NeedRoomCards;
									break;
								}
							}
							else
							{// 登录棋牌圈，但是玩家人在目标服务器
								uint32 cardsNum = 0;	// 房卡数量
								String extra_info;
								Json::Value valItem;
								valItem["gz_id"] = bank.gz_id;
								valItem["model_id"] = cb.data1;
								valItem["pid"] = pid;
								valItem["agent_id"] = agent_id;
								
								Json::FastWriter w;
								String strData = w.write(valItem);
								cardsNum = sGLMgr.GetItemNumByGzid(strData, extra_info);
								
								if(cardsNum == 0)
								{
									valItem["gz_id"] = uint32(pUser->getUInt32Field("gz_id"));
									strData = w.write(valItem);
									cardsNum = sGLMgr.GetItemNumByGzid(strData, extra_info);
								}
								
								if(cardsNum < cb.data2)
								{
									result = enJoinChannel_NeedRoomCards;
									break;
								}
							}
						}
					}
				}
			}
		}
		else if(cb.pay_mode == enPayMode_LoopPay && !bFindChar)
		{// 扣对局费模式，玩家没有进入过牌桌
			Json::Value valPlayChoose;
			reader.parse(cb.sdata2, valPlayChoose);
			
			uint32 join_limit = 0;
			if(valPlayChoose.isMember("ticket_coins") && cb.data4 == 0)	// 未设置观战的才需要检查进入的铜钱
				join_limit = valPlayChoose["ticket_coins"].asUInt();
			
			if(bank.status == CenterBankManager::BankStatusPrep)
			{// 检测缓存到银行的金币
		
				if(cb.club_id && cb.club_room_id && valData2.isMember("ticket_coins"))
				{// 判断俱乐部当前分数
					if(sCenterClubMemberMgr.GetMemberCurrCoins(cb.club_id, pChr) < valData2["ticket_coins"].asUInt())
					{// 进入限制不足
						result = enJoinChannel_NeedRoomCards;
						break;
					}
				}
				else
				{
					if(join_limit && bank.data1 < join_limit)
					{
						result = enJoinChannel_NeedRoomCards;
						break;
					}
				}
			}
			else
			{// 不在目标游戏中
				if(!sXmlDataMgr.IsInGameIds(cb.game_id))
				{// 从其他游戏要往目标游戏跳转之前，验证AA费是否充足
					if(cb.club_id && cb.club_room_id && valData2.isMember("ticket_coins"))
					{// 判断俱乐部当前分数
						if(sCenterClubMemberMgr.GetMemberCurrCoins(cb.club_id, pChr) < valData2["ticket_coins"].asUInt())
						{// 进入限制不足
							result = enJoinChannel_NeedRoomCards;
							break;
						}
					}
					
					uint32 register_time = pUser->getUInt32Field("reg_time");
					if(register_time && register_time + 10 >= time(0))
					{// 刚好注册等待财富到账
						uint32 check_time = now();
						uint32 check_count = 0;
						bool bEoungh = false;
						while(check_count < 10)
						{
							if(check_time + 500 <= now())
							{
								if(join_limit && sGLMgr.GetItemNum(pChr, cb.data1) < join_limit)
								{// 未达到条件
									++check_count;
									check_time = now();
								}
								else
								{// 满足条件
									bEoungh = true;
									break;
								}
							}
						}
						
						if(!bEoungh)
						{// 房费不足
							result = enJoinChannel_NeedRoomCards;
							break;
						}
					}
					else
					{// 旧账号检测
						uint32 curr_gameid = sGLMgr.GetTargetServerGameid(bank.gz_id, agent_id);
						if(curr_gameid != cb.game_id)
						{// 玩家所在服务器和目标组局服务器不在同一个服务器里
							
							if(!sXmlDataMgr.IsInGameIds(curr_gameid))
							{// 银行标记的玩家所在服务器，和登录的服务器不是同一服务器，需尝试让玩家先退出目标服务器
								Json::Value val;
								val["gz_id"] = uint32(bank.gz_id);
								val["platform_id"] = uint32(pUser->getUInt32Field("platform_id"));
								val["agent_id"] = uint32(pUser->getUInt32Field("reg_from"));
								
								Json::FastWriter w;
								if(sGLMgr.SendExitGameServerGateway(w.write(val)))
								{
									pChr->setUInt32Field("ishere", pUser->getUInt32Field("gz_id"));
									uint8 ishere = pUser->getUInt32Field("gz_id");
									
									uint16 currGZID = 0;
									sBankMgr.JoinGameServer(pUser, ishere, &currGZID);
								}
								else
								{
									result = enJoinChannel_InOtherChannel;
									break;
								}
							}
							
							// 判断房费够不够
							if(join_limit && sGLMgr.GetItemNum(pChr, cb.data1) < join_limit)
							{
								result = enJoinChannel_NeedRoomCards;
								break;
							}
						}
					}
				}
			}
		}
		
		Json::Value blackVal;
		reader.parse(cb.black_list, blackVal);
		
		if(blackVal.size())
		{// 黑名单玩家无法进入牌桌
			for (Json::Value::iterator iterVal=blackVal.begin(); iterVal!=blackVal.end(); ++iterVal)
			{
				uint32 pid = StringConverter::parseUnsignedInt(iterVal.key().asString());
				if(pid == pUser->getUInt32Field("platform_id"))
				{// 判断黑名单玩家
					result = enJoinChannel_HasBeenKicked;
					break;
				}
			}
		}
		
		if(!AddPlayerDataToCenterBattle(pChr, cb, pos))
		{
			result = enResult_Failed;
			break;
		}
		
		if(result != enResult_Sucess)
			break;
		
		if(!sXmlDataMgr.IsInGameIds(cb.game_id))
		{
			result = enJoinChannel_ReturnServerID;
			break;
		}
		
		pJoinChannel = sChannelMgr.getByHandle(cb.channel_id);
		if(pJoinChannel.isNull())
		{// 牌桌不存在或者已经结束
			result = enJoinChannel_ChannelNull;
			break;
		}
		
		pJoinTown = sTownMgr.getByHandle(pJoinChannel->getUInt32Field("town_id"));
		if(pJoinTown.isNull())
		{// 房间不存在
			result = enJoinChannel_ChannelNull;
			break;
		}
		
		pCII = TO_CHANNEL_BASE_INTERFACE(pJoinChannel->getAIInterface());
		if(!pCII)
		{// 接口获取失败
			result = enJoinChannel_ChannelNull;
			break;
		}
		
		// 设置牌桌基类接口的座位
		if(pos != 255)
			pAiChrInfe->SetWantSitPos(pos);										
		
		// 牌桌加入结果
		result = pCII->JoinChannel(pChr, false);
		
	}while(0);
	
	Log.Debug("CenterBattleManager::JoinCenterBattle","pid[%u] want joinchannel join_code[%s] result[%u] time_now[%u]", pid, join_code.c_str(), result, now());
	
	if(result == enResult_Sucess)
	{// 成功 加入玩家数据到player，更新cb数据
		
		if(!bPlaying)
		{
			Json::Reader reader;
			Json::Value val;
			reader.parse(cb.player, val);
			
			bool bFindChar = false;
			for(Json::Value::iterator iterVal=val.begin(); iterVal!=val.end(); ++iterVal)
			{
				// if(pChr->getHandle() == (*iterVal)["cid"].asUInt())
				if(pid == (*iterVal)["pid"].asUInt())
				{
					bFindChar = true;
					(*iterVal)["player_status"] = enCenterBattlePlayerStatus_Free;	//状态设置空闲
					(*iterVal)["cid"] = uint32(pChr->getHandle());					//char_id
					break;
				}
			}
			
			if(!bFindChar)
			{// 新增加玩家数据
				
				char str[256] = "";
				sprintf(str, "%u", uint32(pUser->getUInt32Field("platform_id")));
				
				val[str]["pid"] = pUser->getUInt32Field("platform_id");				// PID
				val[str]["cid"] = uint32(pChr->getHandle());						// CID
				val[str]["name"] = string_url_encode(pChr->getStringField("name")); // 昵称
				val[str]["desc"] = string_url_encode(pChr->getStringField("desc"));	// 头像
				val[str]["winlose"] = 0;											// 输赢积分
				val[str]["player_count"] = 0;										// 总游戏局属
				val[str]["player_status"] = enCenterBattlePlayerStatus_Free;		// 角色状态（空闲 游戏中 离开 结束游戏）
				if(pos != 255)
				{
					val[str]["pos"] = pos;											// 设置座位属性
				}
			}
			
			Json::FastWriter w;
			cb.player = w.write(val);
			
			// 将角色ID加入进入过的列表
			String strJoinPlayers = cb.sdata1;
			if(strJoinPlayers.empty())
			{
				strJoinPlayers += "|";
				strJoinPlayers += StringConverter::toString(pUser->getUInt32Field("platform_id"));
				strJoinPlayers += "|";
				
				cb.sdata1 = strJoinPlayers;
			}
			else
			{
				bool bFindChar = false;
				std::vector<String> vStr = StringUtil::split(strJoinPlayers,"|");
				std::vector<String>::iterator iter,ei = vStr.end();
				for(iter = vStr.begin(); iter!=ei; ++iter)
				{
					if(StringConverter::parseUnsignedInt(*iter) == pUser->getUInt32Field("platform_id"))
					{
						bFindChar = true;
						break;
					}
				}
				
				if(!bFindChar)
				{// 增加玩家ID到进入列表中
					strJoinPlayers += StringConverter::toString(pUser->getUInt32Field("platform_id"));
					strJoinPlayers += "|";
					cb.sdata1 = strJoinPlayers;
				}
			}
			
			{
				WGS_CENTERBATTLE_LOCK
				if(!UpdateCenterBattle(cb))
				{// 数据更新失败
					result = enJoinChannel_DataUpdateFailed;
				}
				else
				{
					// 更新玩家组局行踪
					sBankMgr.UpdateZujuTrackInfo(pChr, cb.cb_id, cb.game_id, cb.gz_id, cb.join_code);
					
					WorldPacket packet;
					if(sProtocolsMgr.CreateCenterBattleInfoPacket(&packet, cb))
						sGLMgr.SendProtocolsToChr(pChr,&packet);
				}
			}
		}
	}
	
	// 发送操作结果包
	WorldPacket packet;
	if(sProtocolsMgr.CreateCenterBattleJoinPacket(&packet, join_code.c_str(), cb.gz_id, result))
		sGLMgr.SendProtocolsToChr(pChr, &packet);
	
	return true;
}

// 玩家加入组局列表数据
bool CenterBattleManager::AddPlayerDataToCenterBattle(CharPtr & pChr, CenterBattle & cb, const uint8 & pos)
{
	if(pChr.isNull() || cb.cb_id == 0)
		return false;
	
	UserPtr pUser = sUserMgr.getByHandle(pChr->getUInt32Field("userid"));
	if(pUser.isNull())
		return false;
	
	Json::Reader reader;
	Json::Value valPlayer;
	reader.parse(cb.player, valPlayer);
	
	bool bCharExist = false;
	for(Json::Value::iterator iterVal=valPlayer.begin(); iterVal!=valPlayer.end(); ++iterVal)
	{
		if(pUser->getUInt32Field("platform_id") == (*iterVal)["pid"].asUInt())
		{
			(*iterVal)["cid"] = uint32(pChr->getHandle());
			bCharExist = true;
			break;
		}
	}
	
	if(!bCharExist)
	{// 新增加玩家数据
		
		char str[256] = "";
		sprintf(str, "%u", uint32(pUser->getUInt32Field("platform_id")));
		
		valPlayer[str]["pid"] = pUser->getUInt32Field("platform_id");				// PID
		valPlayer[str]["cid"] = 0;													// CID
		valPlayer[str]["name"] = string_url_encode(pChr->getStringField("name")); 	// 昵称
		valPlayer[str]["desc"] = string_url_encode(pChr->getStringField("desc"));	// 头像
		valPlayer[str]["winlose"] = 0;												// 输赢积分
		valPlayer[str]["player_count"] = 0;											// 总游戏局属
		valPlayer[str]["player_status"] = enCenterBattlePlayerStatus_Free;			// 角色状态（空闲 游戏中 离开 结束游戏）
		if(pos != 255)
			valPlayer[str]["pos"] = pos;											// 设置座位
	}
	
	Json::FastWriter writer;
	cb.player = writer.write(valPlayer);
	
	// 将角色ID加入进入过的列表
	String strJoinPlayers = cb.sdata1;
	if(strJoinPlayers.empty())
	{
		strJoinPlayers += "|";
		strJoinPlayers += StringConverter::toString(pUser->getUInt32Field("platform_id"));
		strJoinPlayers += "|";
		
		cb.sdata1 = strJoinPlayers;
	}
	else
	{
		bool bFindChar = false;
		std::vector<String> vStr = StringUtil::split(strJoinPlayers,"|");
		std::vector<String>::iterator iter,ei = vStr.end();
		for(iter = vStr.begin(); iter!=ei; ++iter)
		{
			if(StringConverter::parseUnsignedInt(*iter) == pUser->getUInt32Field("platform_id"))
			{
				bFindChar = true;
				break;
			}
		}
		
		if(!bFindChar)
		{// 增加玩家ID到进入列表中
			strJoinPlayers += StringConverter::toString(pUser->getUInt32Field("platform_id"));
			strJoinPlayers += "|";
			cb.sdata1 = strJoinPlayers;
		}
	}
	
	if(!UpdateCenterBattle(cb))
	{// 数据更新失败
		return false;
	}
	else
	{// 更新玩家组局行踪
		sBankMgr.UpdateZujuTrackInfo(pChr, cb.cb_id, cb.game_id, cb.gz_id, cb.join_code);
	}
	
	return true;
}

// 创建或者加入组局
bool CenterBattleManager::CreateOrJoinCenterBattle(CharPtr & pChr, String join_params)
{
	if(pChr.isNull() || join_params.empty())
		return false;
	
	UserPtr pUser = sUserMgr.load(pChr->getUInt32Field("userid"));
	if(pUser.isNull())
		return false;
	
	Json::Value val;
	Json::Reader reader;
	if(!reader.parse(join_params, val))
		return false;
	
	String query_params = ServerDatabase.EscapeString(join_params);
	
	uint32 my_gzid = pUser->getUInt32Field("gz_id");	// 请求游戏的玩家分区ID
	String str_MyIp = pUser->getStringField("ip");		// 玩家最后登录IP
	
	uint32 game_id = 0;				// 游戏ID
	if(val.isMember("game_id"))
		game_id = val["game_id"].asUInt();
	
	uint32 gz_id = 0;				// 分区ID
	if(val.isMember("gz_id"))
		gz_id = val["gz_id"].asUInt();
	
	uint32 mode = 0;				// 游戏模式
	if(val.isMember("mode_id"))
		mode = val["mode_id"].asUInt();
	
	uint32 base_coins = 0;			// 底分
	if(val.isMember("base_coins"))
		base_coins = val["base_coins"].asUInt();
	
	uint32 ticket_coins = 0;		// 进入限制
	if(val.isMember("ticket_coins"))
		ticket_coins = val["ticket_coins"].asUInt();
	
	uint32 money_type = 0;			//  货币类型
	if(val.isMember("money_type"))
		money_type = val["money_type"].asUInt();
	
	uint32 pay_mode = 0;			// 付费模式
	if(val.isMember("pay_mode"))
		pay_mode = val["pay_mode"].asUInt();
	
	uint32 top_times = 0;			// 封顶
	if(val.isMember("limit"))
		top_times = val["limit"].asUInt();
	
	uint32 round_num = 0;			// 局数
	if(val.isMember("round_num"))
		round_num = val["round_num"].asUInt();
	
	// 公开房（0 私有 1 公开）
	uint32 isPublic = 0;
	if(val.isMember("isPublic"))
		isPublic = val["isPublic"].asUInt();
	
	// 中途加入（默认是可以的）
	uint32 zhongtujiaru = 1;
	if(val.isMember("isZhongTuJiaRu"))
		zhongtujiaru = val["isZhongTuJiaRu"].asUInt();
	
	// 俱乐部ID
	uint32 club_id = 0;
	if(val.isMember("club_id"))
		club_id = val["club_id"].asUInt();
	
	// 俱乐部房间ID
	uint32 club_room_id = 0;
	if(val.isMember("club_room_id"))
		club_room_id = val["club_room_id"].asUInt();
	
#ifdef CENTERMATCH
	// 赛区ID
	uint32 zone_id = 0;
	if(val.isMember("zone_id"))
		zone_id = val["zone_id"].asUInt();
	
	if(zone_id && !sCenterMatchZoneMgr.IsMatchZoneCanJoin(zone_id))
	{// 赛区不可进
		Log.Debug("CenterBattleManager::CreateOrJoinCenterBattle","===============================2");
		WorldPacket packet;
		if(sProtocolsMgr.CreateCreateOrJoinRandomCenterBattle(&packet, "", 0, 0))
			sGLMgr.SendProtocolsToChr(pChr, &packet);
		return false;
	}
#endif

	isPublic = 1;
	
	uint32 agent_id = pUser->getUInt32Field("reg_from");
	stCenterBattleOpenCoins stCBOC = sXmlDataMgr.GetCenterBattleOpenCoins(agent_id, game_id, money_type, 0, round_num, mode);
	Log.Debug("CenterBattleManager::CreateOrJoinCenterBattle","agent_id[%u] game_id[%u] money_type[%u] round_num[%u] mode[%u]", 
																agent_id, game_id, money_type, round_num, mode);
	
WGS_CENTERBATTLE_LOCK
	
	CenterBattle cb;
	
	if(club_room_id)
	{// 俱乐部房间要超时了 就不让玩家进入了
		CenterClubRoom ccRoom;
		if(!sCenterClubRoomMgr.GetCenterClubRoom(club_room_id, &ccRoom))
			return false;
		
		if(ccRoom.expiry_date == "")
			return false;
		
		uint32 expiry_date = sGLMgr.GetDateTimeSeconds(ccRoom.expiry_date);
		uint32 now_date = time(0);
		if(expiry_date <= now_date)
			return false;
		
		if(expiry_date - now_date <= 5)
		{
			WorldPacket packet;
			if(sProtocolsMgr.CreateCreateOrJoinRandomCenterBattle(&packet, cb.join_code, cb.gz_id, 2))
				sGLMgr.SendProtocolsToChr(pChr, &packet);
			return false;
		}
	}
	
	std::list<CenterBattle> lstData;
	if(club_id)	// 有俱乐部
		GetCenterBattleList(&lstData, "status < 255 and reg_from = %u and game_id = %u and club_id = %u and club_room_id = %u and `istrack` = 1", agent_id, game_id, club_id, club_room_id);
	else		// 无俱乐部
		GetCenterBattleList(&lstData, "status < 255 and reg_from = %u and game_id = %u and club_id = 0 and base_coins = %u and `istrack` = 1", agent_id, game_id, base_coins);
	
	bool bEoungh = true;
	if(club_id)
	{// 俱乐部当前分数
		if(ticket_coins && sCenterClubMemberMgr.GetMemberCurrCoins(club_id, pChr) < ticket_coins)
			bEoungh = false;
	}
	else
	{// 游戏币
		if(ticket_coins && sGLMgr.GetItemNum(pChr, money_type) < ticket_coins)
			bEoungh = false;
	}
	
	if(bEoungh)
	{
		std::list<CenterBattle>::iterator iter, ei = lstData.end();
		for(iter = lstData.begin(); iter!=ei; ++iter)
		{
			if((*iter).status != enBattleStatus_playing && (*iter).status != enBattleStatus_Process)
				continue;
			
			Json::Reader reader;
			Json::Value valP;
			
			if((*iter).game_id == 264)
			{// 炸金花区分模式
				uint32 zjh_huanle = 0;
				uint32 zjhparams_huanle = 0;
				Json::Value valZJH, valZJHParams;
				reader.parse((*iter).sdata2, valZJH);
				if(valZJH.isMember("typeHuanLe"))
				{
					zjh_huanle = valZJH["typeHuanLe"].asUInt();
				}
				
				reader.parse(join_params, valZJHParams);
				if(valZJHParams.isMember("typeHuanLe"))
				{
					zjhparams_huanle = valZJHParams["typeHuanLe"].asUInt();
				}
				
				// 炸金花模式区分
				if(zjh_huanle != zjhparams_huanle)
					continue;
			}
			else
			{
				Json::Value valData, valParams;
				reader.parse((*iter).sdata2, valData);
				reader.parse(join_params, valParams);
				
				if(valData.isMember("typeSubMode") && valParams.isMember("typeSubMode"))
				{// 子玩法相同
					if(valData["typeSubMode"].asUInt() != valParams["typeSubMode"].asUInt())
						continue;
				}
			}
			
			reader.parse((*iter).player, valP);
			Log.Debug("CenterBattleManager::CreateOrJoinCenterBattle","cb_id[%u] valP size[%u]", (*iter).cb_id, valP.size());
			if(valP.size() < (*iter).max_player)
			{// 还在进行中，人数没满的牌桌
				if(stCBOC.bCheckSameIp)
				{// 检查玩家是否同IP
					bool bHaveSameIp = false;
					
					if(!StringUtil::match(str_MyIp, "192.168*"))
					{
						if(valP.size())
						{
							for(Json::Value::iterator iterVal=valP.begin(); iterVal!=valP.end(); ++iterVal)
							{
								uint32 pid = (*iterVal)["pid"].asUInt();
								
								std::list<ResourcePtr> lstUser;
								sUserMgr.getDBObjects(&lstUser, 0, 1, "platform_id = %u and gz_id = %u ", pid, my_gzid);
								if(lstUser.size())
								{
									ResourcePtr pPlayerUser = *lstUser.begin();
									if(pPlayerUser.isNull())
										continue;
									
									if(!str_MyIp.compare(pPlayerUser->getStringField("ip")))
									{// 有同IP玩家
										bHaveSameIp = true;
										break;
									}
								}
							}
						}
					}
					
					// 找到同IP玩家，不让玩家进入该房间
					if(bHaveSameIp)
						continue;
				}
				
				
				cb = (*iter);
				break;
			}
		}
	}
	
	WorldPacket packet;
	if(cb.cb_id)
	{
		Log.Debug("CenterBattleManager::CreateOrJoinCenterBattle","char[%u] game_id[%u] mode[%u] 222", pChr->getHandle(), game_id, mode);
		
		// 先预设玩家列表组局数据
		AddPlayerDataToCenterBattle(pChr, cb);
		
		if(sProtocolsMgr.CreateCreateOrJoinRandomCenterBattle(&packet, cb.join_code, cb.gz_id, 1))
			sGLMgr.SendProtocolsToChr(pChr, &packet);
		if(sProtocolsMgr.CreateCenterBattleJoinPacket(&packet, cb.join_code, cb.gz_id, enJoinChannel_ReturnServerID))
			sGLMgr.SendProtocolsToChr(pChr, &packet);
		return true;
	}
	
	// 如果没有玩家能进入的，创建
	uint8 result = enResult_Sucess;
	do
	{
		Log.Debug("CenterBattleManager::CreateOrJoinCenterBattle","game_id[%u] mode[%u] 222", game_id, mode);
		stCenterBattleMode stMode = sXmlDataMgr.GetCenterBattleModeByGameid(game_id, mode);
		if(!stMode.game_id)
		{// 游戏玩法判断
			result = enCreateBattle_NoThisMode;
			break;
		}
		
		if(stCBOC.model_id == 0)
		{// 错误的配置
			result = enCreateBattle_ErrorLoop;
			break;
		}
		
		if(club_id)
		{// 俱乐部当前分数
			if(ticket_coins && sCenterClubMemberMgr.GetMemberCurrCoins(club_id, pChr) < ticket_coins)
			{
				result = enCreateBattle_GoldTicketNeed;
				break;
			}
		}
		else
		{// 游戏币
			if(ticket_coins && sGLMgr.GetItemNum(pChr, money_type) < ticket_coins)
			{// 进入限制
				result = enCreateBattle_GoldTicketNeed;
				break;
			}
		}
		
		if(club_id && stCBOC.use_club_diamand)
			cb.pid = sCenterClubMgr.GetClubCreaterPid(club_id);	// pid
		else
			cb.pid = pUser->getUInt32Field("platform_id");		// pid
		
		cb.reg_from = pUser->getUInt32Field("reg_from");	// reg_from
		cb.openid = pUser->getStringField("sdata1");		// openid
		
		cb.status = enBattleStatus_Require;					// 申请组局
		cb.gz_id = gz_id;
		cb.game_id = game_id;
		cb.club_id = club_id;
		cb.club_room_id = club_room_id;
		cb.base_coins = base_coins;
		cb.fan_coins = 0;
		cb.limit_loop = round_num;
		cb.top_times = top_times;
		cb.pause = false;
		cb.istrack = isPublic;						// 是否共开房（0 私有 1 公开）
		cb.start_time = time(0);
		cb.create_time = sGLMgr.GetCurDateTime();	// 创建时间
		cb.battle_name = pChr->getStringField("name");	// 房间名称
		cb.sdata2 = join_params;					// 游戏玩法
		cb.mode = mode % 100;						// 游戏模式
		cb.pay_mode = pay_mode;						// 付费模式
		
		cb.data3 = zhongtujiaru;					// 是否可以中途加入
		cb.name = pChr->getStringField("name");		// 房主昵称
		cb.head = pChr->getStringField("desc");		// 房主头像
		cb.update_key = 1;							// 数据更新锁
		cb.data1 = money_type;						// 货币类型
		
		if(!AddCenterBattle(cb))
		{// 创建数据失败
			result = enCreateBattle_CreateDataField;
			break;
		}
	}while(0);
	
	if(sProtocolsMgr.CreateRequireCenterBattleResultPacket(&packet, result))
		sGLMgr.SendProtocolsToChr(pChr,&packet);
	
	if(result == enResult_Sucess)
	{// 发送组局列表
		if(sProtocolsMgr.CreateCenterBattleInfoPacket(&packet, cb))
			sGLMgr.SendProtocolsToChr(pChr,&packet);
		
		// 记录创建日志
		sLogDataMgr.CreateCenterBattleLog(cb.pid, cb.cb_id, cb.game_id, cb.gz_id, cb.data1, cb.data2, enCenterBattleReturnGold_CreateSucess, cb.curr_loop, cb.curr_loop == cb.limit_loop, cb.mode);
		// 记录用户习惯
		Json::Value valCopy;
		valCopy["gz_id"] = gz_id;										// 分区ID
		valCopy["game_id"] = game_id;									// 游戏ID
		valCopy["base_coins"] = base_coins;								// 底分
		valCopy["fan_coins"] = 0;										// 翻分
		valCopy["istrack"] = 0;											// 跟踪（未用）
		valCopy["limit_loop"] = round_num;								// 限制轮次
		valCopy["limit_time"] = 0;										// 限制时间（未用）
		valCopy["top_times"] = top_times;								// 封顶
		valCopy["coins_model"] = 0;										// 初始带入的货币类型（未用）
		valCopy["init_coins"] = 0;										// 初始带入的货币数量（未用）
		valCopy["think_time"] = 0;										// 思考时间（未用）
		valCopy["timeout"] = 0;											// 牌桌超时时间（未用）
		valCopy["battle_name"] = pChr->getStringField("name");			// 房间名称
		valCopy["extra_data"] = join_params;							// 玩法附加数据
		valCopy["mode"] = mode;											// 游戏玩法
		valCopy["pay_mode"] = pay_mode;									// 付费模式
		valCopy["pid"] = uint32(pUser->getUInt32Field("platform_id"));	// 用户PID
		
		Json::FastWriter w;
		String strConfig = w.write(valCopy);
		
		sCRUserConfigMgr.AddCenterBattleConfig(strConfig);
		
		// 网关创建牌桌
		Json::Value valUrl;
		valUrl["gz_id"] = gz_id;
		valUrl["pid"] = uint32(pUser->getUInt32Field("platform_id"));
		valUrl["cb_id"] = uint32(cb.cb_id);
		valUrl["agent_id"] = uint32(pUser->getUInt32Field("reg_from"));
		
		String strShareInfo = "";
		sGLMgr.SendCreateChannelGateway(pChr, w.write(valUrl), strConfig, strShareInfo);
		Log.Debug("CenterBattleManager::PlayerCreateCenterBattle","gz_id[%u]", gz_id);
		
		GetCenterBattle(cb.cb_id, &cb);
		
		if(sProtocolsMgr.CreateCreateOrJoinRandomCenterBattle(&packet, cb.join_code, cb.gz_id, 1))
			sGLMgr.SendProtocolsToChr(pChr, &packet);
		
		// 先预设玩家列表组局数据
		AddPlayerDataToCenterBattle(pChr, cb);
	}
	else
	{
		if(sProtocolsMgr.CreateCreateOrJoinRandomCenterBattle(&packet, cb.join_code, cb.gz_id, 0))
			sGLMgr.SendProtocolsToChr(pChr, &packet);
	}
	
	return true;
}

// 组局换桌（有现成的就加入，没有就创建一个）
bool CenterBattleManager::ChangeJoinCenterBattle(CharPtr & pChr)
{//该逻辑会在游戏服务器中调用
	if(pChr.isNull())
		return false;
	
	uint32 now_time = now();
	std::map<uint32, uint32>::iterator fit = m_mapChangeTableTimer.find(pChr->getHandle());
	if(fit == m_mapChangeTableTimer.end())
	{
		m_mapChangeTableTimer.insert(std::make_pair(pChr->getHandle(), now_time));
	}
	else
	{
		if(fit->second + 3000 >= now_time)
			return false;
		
		fit->second = now_time;
	}
	
	UserPtr pUser = sUserMgr.getByHandle(pChr->getUInt32Field("userid"));
	if(pUser.isNull())
		return false;
	
using namespace AIScript;
	AICreatureBaseInterface * pChrAi = TO_CREATURE_BASE_INTERFACE(pChr->getAIInterface());
	if(!pChrAi)
		return false;
	
	ChannelPtr pChannel = pChrAi->GetChannelPtr();
	if(pChannel.isNull())
		return false;
	
	AIChannelBaseInterface * pCII = TO_CHANNEL_BASE_INTERFACE(pChannel->getAIInterface());
	if(!pCII)
		return false;
	
	// 退出牌桌失败，不能换桌
	if(!pCII->ExitChannel(pChr))
		return false;
	
	uint32 org_cbid = 0;
	String strJsonVal = pChannel->getStringField("info");
	
	Json::Value val;
	Json::Reader reader;
	reader.parse(strJsonVal, val);
	
	// 退出游戏前的组局
	if(val.isMember("cb_id"))
		org_cbid = val["cb_id"].asUInt();
	
	uint32 my_gzid = pUser->getUInt32Field("gz_id");	// 请求游戏的玩家分区ID
	String str_MyIp = pUser->getStringField("ip");		// 玩家最后登录IP
	
	uint32 game_id = 0;				// 游戏ID
	if(val.isMember("game_id"))
		game_id = val["game_id"].asUInt();
	
	uint32 gz_id = 0;				// 分区ID
	if(val.isMember("gz_id"))
		gz_id = val["gz_id"].asUInt();
	
	uint32 top_times = 0;			// 封顶
	if(val.isMember("limit"))
		top_times = val["limit"].asUInt();
	
	uint32 round_num = 0;			// 局数
	if(val.isMember("round_num"))
		round_num = val["round_num"].asUInt();
	
	// 公开房（0 私有 1 公开）
	uint32 isPublic = 0;
	if(val.isMember("isPublic"))
		isPublic = val["isPublic"].asUInt();
	
	String strExtraData = "";
	
	// 中途加入（默认是可以的）
	uint32 zhongtujiaru = 1;
	uint32 typeSubMode = 0;
	uint32 mode = 0;				// 游戏模式
	uint32 base_coins = 0;			// 底分
	uint32 ticket_coins = 0;		// 进入限制
	uint32 exit_coins = 0;			// 离开限制
	uint32 money_type = 0;			// 货币类型
	uint32 pay_mode = 0;			// 付费模式
	if(val.isMember("extra_data"))
	{
		Json::Value val2 = val["extra_data"];
		if(val2.isMember("isZhongTuJiaRu"))
			zhongtujiaru = val2["isZhongTuJiaRu"].asUInt();
		
		if(val2.isMember("typeSubMode"))
			typeSubMode = val2["typeSubMode"].asUInt();
		
		if(val2.isMember("mode_id"))
			mode = val2["mode_id"].asUInt();
		
		if(val2.isMember("base_coins"))
			base_coins = val2["base_coins"].asUInt();
		
		if(val2.isMember("ticket_coins"))
			ticket_coins = val2["ticket_coins"].asUInt();
		
		if(val2.isMember("exit_coins"))
			exit_coins = val2["exit_coins"].asUInt();
		
		if(val2.isMember("money_type"))
			money_type = val2["money_type"].asUInt();
		
		if(val2.isMember("pay_mode"))
			pay_mode = val2["pay_mode"].asUInt();
	
		Json::FastWriter w;
		strExtraData = w.write(val2);
	}
	
	// 俱乐部ID
	uint32 club_id = 0;
	if(val.isMember("club_id"))
		club_id = val["club_id"].asUInt();
	
	// 俱乐部房间ID
	uint32 club_room_id = 0;
	if(val.isMember("club_room_id"))
		club_room_id = val["club_room_id"].asUInt();
	
	isPublic = 1;
	
	uint32 agent_id = pUser->getUInt32Field("reg_from");
	stCenterBattleOpenCoins stCBOC = sXmlDataMgr.GetCenterBattleOpenCoins(agent_id, game_id, money_type, 0, round_num, mode);
	Log.Debug("CenterBattleManager::ChangeJoinCenterBattle","agent_id[%u] game_id[%u] money_type[%u] round_num[%u] mode[%u]", agent_id, game_id, money_type, round_num, mode);
	
WGS_CENTERBATTLE_LOCK
	
	CenterBattle cb;
	std::list<CenterBattle> lstData;
	if(club_id)	// 有俱乐部
		GetCenterBattleList(&lstData, "status < 255 and reg_from = %u and game_id = %u and club_id = %u and club_room_id = %u and `istrack` = 1", agent_id, game_id, club_id, club_room_id);
	else		// 无俱乐部
		GetCenterBattleList(&lstData, "status < 255 and reg_from = %u and game_id = %u and club_id = 0 and base_coins = %u and `istrack` = 1", agent_id, game_id, base_coins);
	
	bool bEoungh = true;
	if(club_id)
	{// 俱乐部当前分数
		if(ticket_coins && sCenterClubMemberMgr.GetMemberCurrCoins(club_id, pChr) < ticket_coins)
			bEoungh = false;
	}
	else
	{// 游戏币
		if(ticket_coins && sGLMgr.GetItemNum(pChr, money_type) < ticket_coins)
			bEoungh = false;
	}
	
	if(bEoungh)
	{
		std::list<CenterBattle>::iterator iter, ei = lstData.end();
		for(iter = lstData.begin(); iter!=ei; ++iter)
		{
			if((*iter).status != enBattleStatus_playing && (*iter).status != enBattleStatus_Process)
				continue;
			
			Json::Reader reader;
			Json::Value valP;
			
			Json::Value valData;
			reader.parse((*iter).sdata2, valData);
			
			if(valData.isMember("typeSubMode") && typeSubMode)
			{// 子玩法相同
				if(valData["typeSubMode"].asUInt() != typeSubMode)
					continue;
			}
			
			if((*iter).cb_id == org_cbid)
			{// 不加入到之前退出的牌局里面
				continue;
			}
			
			reader.parse((*iter).player, valP);
			if(valP.size() < (*iter).max_player)
			{// 还在进行中，人数没满的牌桌
				if(stCBOC.bCheckSameIp)
				{// 检查玩家是否同IP
					bool bHaveSameIp = false;
					
					if(!StringUtil::match(str_MyIp, "192.168*"))
					{
						if(valP.size())
						{
							for(Json::Value::iterator iterVal=valP.begin(); iterVal!=valP.end(); ++iterVal)
							{
								uint32 pid = (*iterVal)["pid"].asUInt();
								
								std::list<ResourcePtr> lstUser;
								sUserMgr.getDBObjects(&lstUser, 0, 1, "platform_id = %u and gz_id = %u ", pid, my_gzid);
								if(lstUser.size())
								{
									ResourcePtr pPlayerUser = *lstUser.begin();
									if(pPlayerUser.isNull())
										continue;
									
									if(!str_MyIp.compare(pPlayerUser->getStringField("ip")))
									{// 有同IP玩家
										bHaveSameIp = true;
										break;
									}
								}
							}
						}
					}
					
					// 找到同IP玩家，不让玩家进入该房间
					if(bHaveSameIp)
						continue;
				}
				
				
				cb = (*iter);
				break;
			}
		}
	}
	
	WorldPacket packet;
	if(cb.channel_id)
	{// 找到牌桌，让玩家加入牌桌
		ChannelPtr pNewChn = sChannelMgr.getByHandle(cb.channel_id);
		if(pNewChn.isNull())
			return false;
		
		AIChannelBaseInterface * pChnBase = TO_CHANNEL_BASE_INTERFACE(pNewChn->getAIInterface());
		if(!pChnBase)
			return false;
		
		bool re = pChnBase->JoinChannel(pChr);
		if(re)
		{
			Json::Reader reader;
			Json::Value valP;
			reader.parse(cb.player, valP);
			char str[256] = "";
			sprintf(str, "%u", uint32(pUser->getUInt32Field("platform_id")));
			
			valP[str]["pid"] = pUser->getUInt32Field("platform_id");				// PID
			valP[str]["cid"] = uint32(pChr->getHandle());							// CID
			valP[str]["name"] = string_url_encode(pChr->getStringField("name"));	// 昵称
			valP[str]["desc"] = string_url_encode(pChr->getStringField("desc"));	// 头像
			valP[str]["winlose"] = 0;												// 输赢积分
			valP[str]["player_count"] = 0;											// 总游戏局属
			valP[str]["player_status"] = enCenterBattlePlayerStatus_Free;			// 角色状态（空闲 游戏中 离开 结束游戏）
			
			Json::FastWriter w;
			cb.player = w.write(valP);
			
			// 将角色ID加入进入过的列表
			String strJoinPlayers = cb.sdata1;
			if(strJoinPlayers.empty())
			{
				strJoinPlayers += "|";
				strJoinPlayers += StringConverter::toString(pUser->getUInt32Field("platform_id"));
				strJoinPlayers += "|";
				
				cb.sdata1 = strJoinPlayers;
			}
			else
			{
				bool bFindChar = false;
				std::vector<String> vStr = StringUtil::split(strJoinPlayers,"|");
				std::vector<String>::iterator iter,ei = vStr.end();
				for(iter = vStr.begin(); iter!=ei; ++iter)
				{
					if(StringConverter::parseUnsignedInt(*iter) == pUser->getUInt32Field("platform_id"))
					{
						bFindChar = true;
						break;
					}
				}
				
				if(!bFindChar)
				{// 增加玩家ID到进入列表中
					strJoinPlayers += StringConverter::toString(pUser->getUInt32Field("platform_id"));
					strJoinPlayers += "|";
					cb.sdata1 = strJoinPlayers;
				}
			}
			
			sBankMgr.UpdateZujuTrackInfo(pChr, cb.cb_id, cb.game_id, cb.gz_id, cb.join_code);
			UpdateCenterBattle(cb);
		}
		
		return re;
	}
	
	// 如果没有玩家能进入的，创建
	uint8 result = enResult_Sucess;
	do
	{
		stCenterBattleMode stMode = sXmlDataMgr.GetCenterBattleModeByGameid(game_id, mode);
		if(!stMode.game_id)
		{// 游戏玩法判断
			result = enCreateBattle_NoThisMode;
			break;
		}
		
		if(stCBOC.model_id == 0)
		{// 错误的配置
			result = enCreateBattle_ErrorLoop;
			break;
		}
		
		if(club_id)
		{// 俱乐部当前分数
			if(ticket_coins && sCenterClubMemberMgr.GetMemberCurrCoins(club_id, pChr) < ticket_coins)
			{
				result = enCreateBattle_GoldTicketNeed;
				break;
			}
		}
		else
		{// 游戏币
			if(ticket_coins && sGLMgr.GetItemNum(pChr, money_type) < ticket_coins)
			{// 进入限制
				result = enCreateBattle_GoldTicketNeed;
				break;
			}
		}
		
		if(club_id && stCBOC.use_club_diamand)
			cb.pid = sCenterClubMgr.GetClubCreaterPid(club_id);	// pid
		else
			cb.pid = pUser->getUInt32Field("platform_id");		// pid
		
		cb.reg_from = pUser->getUInt32Field("reg_from");	// reg_from
		cb.openid = pUser->getStringField("sdata1");		// openid
		
		cb.status = enBattleStatus_Require;					// 申请组局
		cb.gz_id = gz_id;
		cb.game_id = game_id;
		cb.club_id = club_id;
		cb.club_room_id = club_room_id;
		cb.base_coins = base_coins;
		cb.fan_coins = 0;
		cb.limit_loop = round_num;
		cb.top_times = top_times;
		cb.pause = false;
		cb.istrack = isPublic;						// 是否共开房（0 私有 1 公开）
		cb.start_time = time(0);
		cb.create_time = sGLMgr.GetCurDateTime();	// 创建时间
		cb.battle_name = pChr->getStringField("name");	// 房间名称
		cb.sdata2 = strExtraData;					// 游戏玩法
		cb.mode = mode ;							// 游戏模式
		cb.pay_mode = pay_mode;						// 付费模式
		
		cb.data3 = zhongtujiaru;					// 是否可以中途加入
		cb.name = pChr->getStringField("name");		// 房主昵称
		cb.head = pChr->getStringField("desc");		// 房主头像
		cb.update_key = 1;							// 数据更新锁
		cb.data1 = money_type;						// 货币类型
		
		if(!AddCenterBattle(cb))
		{// 创建数据失败
			result = enCreateBattle_CreateDataField;
			break;
		}
	}while(0);
	
	if(result == enResult_Sucess)
	{// 发送组局列表
		stPlayerCreateCenterBattle stPCB;
		
		stPCB.cb_id = cb.cb_id;
		stPCB.pid = cb.pid;
		stPCB.gz_id = cb.gz_id;
		stPCB.game_id = cb.game_id;
		stPCB.base_coins = cb.base_coins;
		stPCB.fan_coins = cb.fan_coins;
		
		stPCB.mode = cb.mode;
		stPCB.istrack = cb.istrack;
		stPCB.limit_loop = cb.limit_loop;
		stPCB.limit_time = cb.limit_time;
		stPCB.top_times = cb.top_times;
		
		stPCB.coins_model = cb.coins_model;
		stPCB.init_coins = cb.init_coins;
		
		stPCB.think_time = cb.think_time;
		stPCB.timeout = cb.timeout;
		
		stPCB.name = cb.name;
		stPCB.battle_name = cb.battle_name;
		stPCB.extra_data = cb.sdata2;
		
		ChannelPtr pChannel = sGLMgr.CreateCenterChannel(stPCB);
		if(pChannel.isNull())
		{// 创建牌桌失败
			return false;
		}
		Log.Debug("CenterBattleManager::ChangeJoinCenterBattle","=================================15");
		cb.status = enBattleStatus_Process;					// 更新状态
		cb.join_code = pChannel->getStringField("winner");	// 进入码
		cb.channel_id = pChannel->getHandle();				// 牌桌ID
		
	using namespace AIScript;
		AIChannelBaseInterface * pChnAi = TO_CHANNEL_BASE_INTERFACE(pChannel->getAIInterface());
		if(!pChnAi)
			return false;
		Log.Debug("CenterBattleManager::ChangeJoinCenterBattle","=================================16");
		cb.max_player = pChnAi->GetMaxPlayerNum();
		
		bool re = pChnAi->JoinChannel(pChr);
		if(re)
		{
			Json::Reader reader;
			Json::Value valP;
			reader.parse(cb.player, valP);
			
			char str[256] = "";
			sprintf(str, "%u", uint32(pUser->getUInt32Field("platform_id")));
			
			valP[str]["pid"] = pUser->getUInt32Field("platform_id");				// PID
			valP[str]["cid"] = uint32(pChr->getHandle());							// CID
			valP[str]["name"] = string_url_encode(pChr->getStringField("name"));	// 昵称
			valP[str]["desc"] = string_url_encode(pChr->getStringField("desc"));	// 头像
			valP[str]["winlose"] = 0;												// 输赢积分
			valP[str]["player_count"] = 0;											// 总游戏局属
			valP[str]["player_status"] = enCenterBattlePlayerStatus_Free;			// 角色状态（空闲 游戏中 离开 结束游戏）
			
			Json::FastWriter w;
			cb.player = w.write(valP);
			
			// 将角色ID加入进入过的列表
			String strJoinPlayers = cb.sdata1;
			if(strJoinPlayers.empty())
			{
				strJoinPlayers += "|";
				strJoinPlayers += StringConverter::toString(pUser->getUInt32Field("platform_id"));
				strJoinPlayers += "|";
				
				cb.sdata1 = strJoinPlayers;
			}
			else
			{
				bool bFindChar = false;
				std::vector<String> vStr = StringUtil::split(strJoinPlayers,"|");
				std::vector<String>::iterator iter,ei = vStr.end();
				for(iter = vStr.begin(); iter!=ei; ++iter)
				{
					if(StringConverter::parseUnsignedInt(*iter) == pUser->getUInt32Field("platform_id"))
					{
						bFindChar = true;
						break;
					}
				}
				
				if(!bFindChar)
				{// 增加玩家ID到进入列表中
					strJoinPlayers += StringConverter::toString(pUser->getUInt32Field("platform_id"));
					strJoinPlayers += "|";
					cb.sdata1 = strJoinPlayers;
				}
			}
			
			sBankMgr.UpdateZujuTrackInfo(pChr, cb.cb_id, cb.game_id, cb.gz_id, cb.join_code);
		}
		
		UpdateCenterBattle(cb);
		return re;
	}
	else
	{// 牌桌创建失败
		return false;
	}
	
	return true;
}

// 系统创建组局
bool CenterBattleManager::CreateCenterBattleBySystem(String params)
{
	if(params.empty())
		return false;
	
	Json::Value val;
	Json::Reader reader;
	if(!reader.parse(params, val))
		return false;
	
	uint32 game_id = 0;				// 游戏ID
	if(val.isMember("game_id"))
		game_id = val["game_id"].asUInt();
	
	uint32 gz_id = 0;				// 分区ID
	if(val.isMember("gz_id"))
		gz_id = val["gz_id"].asUInt();
	
	uint32 mode = 0;				// 游戏模式
	if(val.isMember("mode_id"))
		mode = val["mode_id"].asUInt();
	
	uint32 base_coins = 0;			// 底分
	if(val.isMember("base_coins"))
		base_coins = val["base_coins"].asUInt();
	
	/* uint32 ticket_coins = 0;		// 进入限制
	if(val.isMember("ticket_coins"))
		ticket_coins = val["ticket_coins"].asUInt();
	
	uint32 exit_coins = 0;			// 离开限制
	if(val.isMember("exit_coins"))
		exit_coins = val["exit_coins"].asUInt(); */
	
	uint32 club_id = 0;			//  俱乐部ID
	if(val.isMember("club_id"))
		club_id = val["club_id"].asUInt();
	
	uint32 club_room_id = 0;	//  俱乐部房间ID
	if(val.isMember("club_room_id"))
		club_room_id = val["club_room_id"].asUInt();
	
	uint32 money_type = 0;			//  货币类型
	if(val.isMember("money_type"))
		money_type = val["money_type"].asUInt();
	
	uint32 pay_mode = 0;			// 付费模式
	if(val.isMember("pay_mode"))
		pay_mode = val["pay_mode"].asUInt();
	
	uint32 agent_id = 0;			// 代理商ID
	if(val.isMember("agent_id"))
		agent_id = val["agent_id"].asUInt();
	
	uint32 top_times = 0;			// 封顶
	if(val.isMember("limit"))
		top_times = val["limit"].asUInt();
	
	uint32 round_num = 0;			// 局数
	if(val.isMember("round_num"))
		round_num = val["round_num"].asUInt();
	
	// 公开房（0 私有 1 公开）
	uint32 isPublic = 0;
	if(val.isMember("isPublic"))
		isPublic = val["isPublic"].asUInt();
	
	// 中途加入（默认是可以的）
	uint32 zhongtujiaru = 1;
	isPublic = 1;
	
	stCenterBattleOpenCoins stCBOC = sXmlDataMgr.GetCenterBattleOpenCoins(agent_id, game_id, money_type, 0, round_num, mode);
	
WGS_CENTERBATTLE_LOCK
	
	// 创建组局
	CenterBattle cb;
	uint8 result = enResult_Sucess;
	do
	{
		stCenterBattleMode stMode = sXmlDataMgr.GetCenterBattleModeByGameid(game_id, mode);
		if(!stMode.game_id)
		{// 游戏玩法判断
			result = enCreateBattle_NoThisMode;
			break;
		}
		
		if(stCBOC.model_id == 0)
		{// 错误的配置
			result = enCreateBattle_ErrorLoop;
			break;
		}
		
		cb.pid = 0;					// pid
		cb.reg_from = agent_id;		// reg_from
		
		cb.status = enBattleStatus_Require;					// 申请组局
		cb.gz_id = gz_id;
		cb.game_id = game_id;
		cb.base_coins = base_coins;
		cb.fan_coins = 0;
		cb.limit_loop = round_num;
		cb.top_times = top_times;
		cb.pause = false;
		cb.istrack = isPublic;						// 是否共开房（0 私有 1 公开）
		cb.club_id = club_id;						// 俱乐部ID
		cb.club_room_id = club_room_id;				// 俱乐部房间ID
		cb.start_time = time(0);
		cb.create_time = sGLMgr.GetCurDateTime();	// 创建时间
		cb.sdata2 = params;							// 游戏玩法
		cb.mode = mode % 100;						// 游戏模式
		cb.pay_mode = pay_mode;						// 付费模式
		
		cb.data3 = zhongtujiaru;					// 是否可以中途加入
		cb.update_key = 1;							// 数据更新锁
		cb.data1 = money_type;						// 货币类型
		cb.data5 = 1;								// 永不删除
		
		if(!AddCenterBattle(cb))
		{// 创建数据失败
			result = enCreateBattle_CreateDataField;
			break;
		}
		
	}while(0);
	
	if(result == enResult_Sucess)
	{// 发送组局列表
		stPlayerCreateCenterBattle stPCB;
		uint8 result = enResult_Sucess;
		do
		{
			stPCB.cb_id = cb.cb_id;
			stPCB.pid = cb.pid;
			stPCB.gz_id = cb.gz_id;
			stPCB.game_id = cb.game_id;
			stPCB.base_coins = cb.base_coins;
			stPCB.fan_coins = cb.fan_coins;
			
			stPCB.mode = cb.mode;
			stPCB.istrack = cb.istrack;
			stPCB.limit_loop = cb.limit_loop;
			stPCB.limit_time = cb.limit_time;
			stPCB.top_times = cb.top_times;
			
			stPCB.coins_model = cb.coins_model;
			stPCB.init_coins = cb.init_coins;
			
			stPCB.think_time = cb.think_time;
			stPCB.timeout = cb.timeout;
			
			stPCB.name = cb.name;
			stPCB.battle_name = cb.battle_name;
			stPCB.extra_data = cb.sdata2;
			
			ChannelPtr pChannel = sGLMgr.CreateCenterChannel(stPCB);
			if(pChannel.isNull())
			{// 创建牌桌失败
				result = enCreateGameBattle_CreateFailed;
				break;
			}
			
			cb.status = enBattleStatus_Process;					// 更新状态
			cb.join_code = pChannel->getStringField("winner");	// 进入码
			cb.channel_id = pChannel->getHandle();				// 牌桌ID
		using namespace AIScript;
			
			AIChannelBaseInterface * pChnAi = TO_CHANNEL_BASE_INTERFACE(pChannel->getAIInterface());
			if(!pChnAi)
			{
				result = enCreateGameBattle_CreateFailed;
				break;
			}
			
			cb.max_player = pChnAi->GetMaxPlayerNum();
			if(!UpdateCenterBattle(cb, 0))
			{
				result = enCreateGameBattle_DataUpdateFailed;
				break;
			}
			
			if(cb.club_id)
			{// 玩家【%s】在%s创建了牌桌，消耗%u钻石
				char buf[256] = "";
				sprintf(buf, sMsg.getMessage("club_createbattle_message").c_str(), cb.name.c_str(), sGLMgr.GetCurDateTime().c_str(), cb.data2);
				
				String strMessage = buf;
				sCenterClubMessageMgr.AddSystemChatMessage(strMessage, cb.reg_from, cb.club_id);
			}
			
		}while(0);
		
		return result;
	}
	
	return true;
}

// 获取斗地主公共组局列表
void CenterBattleManager::GetDDZPublicBattleList(CharPtr & pChr, String params)
{
	if(pChr.isNull())
		return ;
	
	UserPtr pUser = sUserMgr.getByHandle(pChr->getUInt32Field("userid"));
	if(pUser.isNull())
		return ;
	
	Json::Value val;
	Json::Reader reader;
	reader.parse(params, val);
	
	if(val.empty())
		return ;
	
	if(!val.isMember("game_id") || !val.isMember("gz_id") || !val.isMember("room_id") || 
		!val.isMember("hall_id") || !val.isMember("offset") || !val.isMember("num"))
		return ;
	
	uint32 game_id = val["game_id"].asUInt();	// 游戏ID
	uint32 gz_id = val["gz_id"].asUInt();		// 分区ID
	uint32 room_id = val["room_id"].asUInt();	// 房间ID
	uint32 hall_id = val["hall_id"].asUInt();	// 大厅ID
	uint32 offset = val["offset"].asUInt();		// 偏移
	uint32 num = val["num"].asUInt();			// 请求数量
	
	Log.Debug("CenterBattleManager::GetDDZPublicBattleList","game_id[%u] gz_id[%u] room_id[%u] hall_id[%u] offset[%u] num[%u]", game_id, gz_id, room_id, hall_id, offset, num);
	std::list<CenterBattle> lstData, lstTTData, lstResultData;
	GetCenterBattleList(&lstData, "status < 255 and reg_from = %u and `game_id` = %u and `gz_id` = %u ", pUser->getUInt32Field("reg_from"), game_id, gz_id);
	
	std::list<CenterBattle>::iterator iter, ei = lstData.end();
	for(iter = lstData.begin(); iter!=ei; ++iter)
	{
		Json::Value val2;
		reader.parse((*iter).sdata2, val2);
		
		if((val2.isMember("room_id") && val2["room_id"].asUInt() == room_id) && 
			(val2.isMember("hall_id") && val2["hall_id"].asUInt() == hall_id))
		{
			lstTTData.push_back(*iter);
		}
	}
	
	uint32 total_count = lstTTData.size();	// 总数
	uint32 index = 0;
	std::list<CenterBattle>::iterator itB, eiB = lstTTData.end();
	for(itB = lstTTData.begin(); itB!=eiB; ++itB)
	{
		if(offset > index++)
			continue;
		
		if(offset + num >= index)
		{
			lstResultData.push_back(*itB);
		}
		else
		{
			break;
		}
	}
	
	WorldPacket packet;
	if(sProtocolsMgr.CreateDDZPublicCenterBattleListPacket(&packet, room_id, hall_id, total_count, offset, num, lstResultData))
		sGLMgr.SendProtocolsToChr(pChr, &packet);	
}

// 获取俱乐部选择组局列表
void CenterBattleManager::GetClubChooseSeatBattleList(CharPtr & pChr, String params)
{
	if(pChr.isNull())
		return ;
	
	UserPtr pUser = sUserMgr.getByHandle(pChr->getUInt32Field("userid"));
	if(pUser.isNull())
		return ;
	
	Json::Value val;
	Json::Reader reader;
	reader.parse(params, val);
	
	if(val.empty())
		return ;
	
	if(!val.isMember("game_id") || !val.isMember("gz_id") || !val.isMember("club_id") || 
		!val.isMember("room_id") || !val.isMember("offset") || !val.isMember("num"))
		return ;
	
	uint32 game_id = val["game_id"].asUInt();	// 游戏ID
	uint32 gz_id = val["gz_id"].asUInt();		// 分区ID
	uint32 club_id = val["club_id"].asUInt();	// 俱乐部ID
	uint32 room_id = val["room_id"].asUInt();	// 房间ID
	uint32 offset = val["offset"].asUInt();		// 偏移
	uint32 num = val["num"].asUInt();			// 请求数量
	
	// Log.Debug("CenterBattleManager::GetClubChooseSeatBattleList","game_id[%u] gz_id[%u] club_id[%u] room_id[%u] offset[%u] num[%u]", game_id, gz_id, club_id, room_id, offset, num);
	std::list<CenterBattle> lstData, lstTTData, lstResultData;
	GetCenterBattleList(&lstData, "status < 255 and reg_from = %u and `game_id` = %u and `gz_id` = %u and club_id = %u and club_room_id = %u", 
										pUser->getUInt32Field("reg_from"), game_id, gz_id, club_id, room_id);
	
	// Log.Debug("CenterBattleManager::GetClubChooseSeatBattleList","lstData size[%u]", lstData.size());
	
	std::list<CenterBattle>::iterator iter, ei = lstData.end();
	for(iter = lstData.begin(); iter!=ei; ++iter)
	{
		Json::Value val2;
		reader.parse((*iter).sdata2, val2);
		
		// Log.Debug("CenterBattleManager::GetClubChooseSeatBattleList","cb_id[%u]", (*iter).cb_id);
		if((val2.isMember("club_id") && val2["club_id"].asUInt() == club_id) && 
			(val2.isMember("club_room_id") && val2["club_room_id"].asUInt() == room_id))
		{
			lstTTData.push_back(*iter);
		}
	}
	
	uint32 total_count = lstTTData.size();	// 总数
	uint32 index = 0;
	std::list<CenterBattle>::iterator itB, eiB = lstTTData.end();
	for(itB = lstTTData.begin(); itB!=eiB; ++itB)
	{
		if(offset > index++)
			continue;
		
		if(offset + num >= index)
		{
			lstResultData.push_back(*itB);
		}
		else
		{
			break;
		}
	}
	
	WorldPacket packet;
	if(sProtocolsMgr.CreateClubChooseSeatBattleListPacket(&packet, club_id, room_id, total_count, offset, num, lstResultData))
		sGLMgr.SendProtocolsToChr(pChr, &packet);	
}

// 验证组局牌桌密码
bool CenterBattleManager::SetBattlePasswd(const uint32 & cb_id, String & passwd)
{
	if(cb_id == 0)
		return false;
	
	CenterBattle cb;
	if(!GetCenterBattle(cb_id, &cb))
		return false;
	
	String strData = cb.sdata2;
	
	Json::Value val;
	Json::Reader reader;
	reader.parse(strData, val);
	
	if(passwd.size())
	{// 设置密码
		if(val["isPublic"].asUInt() == 0)
			return false;
		
		val["isPublic"] = 0;
		val["passwd"] = passwd;
	}
	else
	{// 取消密码
		val["isPublic"] = 1;
		val["passwd"] = "";
	}
	
	Json::FastWriter w;
	cb.sdata2 = w.write(val);
	
	return UpdateCenterBattle(cb);
}


// 获得牌桌玩家信息 cb_id 组局ID  char_id 要请求数据的角色ID
stCenterBattlePlayerInfo CenterBattleManager::GetPlayerInfo(const uint32 & cb_id, const uint32 & char_id)
{
	stCenterBattlePlayerInfo player_info;
	
	CenterBattle cb;
	if(!GetCenterBattle(cb_id, &cb))
		return player_info;
	
	Json::Reader reader;
	Json::Value val;
	reader.parse(cb.player, val);
	
	if(val.size())
	{
		for(Json::Value::iterator iterVal=val.begin(); iterVal!=val.end(); ++iterVal)
		{
			if(char_id == (*iterVal)["cid"].asUInt())
			{
				uint32 pid = 0;
				CharPtr pChr = sCharMgr.getByHandle(char_id);
				if(!pChr.isNull())
				{
					UserPtr pUser = sUserMgr.getByHandle(pChr->getUInt32Field("userid"));
					if(!pUser.isNull())
					{
						pid = pUser->getUInt32Field("platform_id");
					}
				}
				
				player_info.pid = pid;
				player_info.cid = char_id;
				player_info.winLose = (*iterVal)["winlose"].asInt();
				player_info.player_count = (*iterVal)["player_count"].asUInt();
				player_info.player_status = (*iterVal)["player_status"].asUInt();
				
				player_info.name = string_url_decode((*iterVal)["name"].asString());
				player_info.desc = string_url_decode((*iterVal)["desc"].asString());
				break;
			}
		}
	}
	
	return player_info;
}

// 更新牌桌玩家信息（可以在CenterBattleLogManager::AddCenterBattleLoopTotalLog函数中调用更新的逻辑）
bool CenterBattleManager::UpdatePlayersInfo(const uint32 & cb_id, std::vector<CenterBattlePlayerWinLose> player_winLose, String strExtraData)
{
WGS_CENTERBATTLE_LOCK
	CenterBattle cb;
	if(!GetCenterBattle(cb_id, &cb))
		return false;
	
	// 更新玩家总局数 总输赢积分
	Json::Reader reader;
	Json::Value val;
	reader.parse(cb.player, val);
	
	std::vector<CenterBattlePlayerWinLose>::iterator iter, ei = player_winLose.end();
	for(iter = player_winLose.begin(); iter!=ei; ++iter)
	{
		bool bFindChar = false;
		for(Json::Value::iterator iterVal=val.begin(); iterVal!=val.end(); ++iterVal)
		{
			if((*iter).char_id == (*iterVal)["cid"].asUInt())
			{// 找到玩家数据
				bFindChar = true;
				(*iterVal)["winlose"] = (*iterVal)["winlose"].asInt() + (*iter).winLoseScore;
				
				Json::Value valEx;
				Json::Reader reader;
				reader.parse((*iter).json_data, valEx);
				
				if(valEx.isMember("banker_loop"))
				{// 有局数直接赋值
					(*iterVal)["player_count"] = valEx["banker_loop"].asUInt();
				}
				else
				{// 没有局数，就累加
					(*iterVal)["player_count"] = (*iterVal)["player_count"].asUInt() + 1;
				}
				
				break;
			}
		}
		
		if(!bFindChar)
		{// 未找到，生成新数据
			char str[256] = "";
			sprintf(str, "%u", (*iter).platform_id);
			
			val[str]["pid"] = (*iter).platform_id;
			val[str]["cid"] = (*iter).char_id;
			val[str]["winlose"] = (*iter).winLoseScore;
			val[str]["player_count"] = 1;
			val[str]["player_status"] = enCenterBattlePlayerStatus_Free;
			
			val[str]["name"] = string_url_encode((*iter).player_nick);
			val[str]["desc"] = string_url_encode((*iter).player_desc);
		}
	}
	
	Json::FastWriter w;
	cb.player = w.write(val);
	cb.sdata3 = strExtraData;
	
	UpdateCenterBattle(cb);
	return true;
}

// 玩家离开组局牌桌
bool CenterBattleManager::PlayerLeaveChannel(const uint32 & cb_id, const uint32 & char_id)
{
WGS_CENTERBATTLE_LOCK
	CenterBattle cb;
	if(!GetCenterBattle(cb_id, &cb))
		return false;
	
	// 玩家有过游戏记录 设置离开状态
	Json::Reader reader;
	Json::Value val, newVal;
	reader.parse(cb.player, val);
	
	Json::FastWriter w;
	bool bRemove = false;
	for(Json::Value::iterator iterVal=val.begin(); iterVal!=val.end(); ++iterVal)
	{
		if(char_id == (*iterVal)["cid"].asUInt())
		{// 找到玩家数据
			if(cb.pay_mode == enPayMode_LoopPay)
			{// 金币场不保留玩家数据
				bRemove = true;
			}
			else
			{
				if((*iterVal)["player_count"].asUInt() > 0)
				{// 有游戏记录，更新玩家为离开状态
					(*iterVal)["player_status"] = enCenterBattlePlayerStatus_LeaveWithScore;
				}
				else
				{// 玩家没有游戏记录，删除
					bRemove = true;
				}
			}
			
			break;
		}
	}
	
	if(bRemove)
	{// 玩家没有游戏记录 直接清除玩家数据
		
		for(Json::Value::iterator iterVal=val.begin(); iterVal!=val.end(); ++iterVal)
		{
			if(char_id == (*iterVal)["cid"].asUInt())
			{// 要删除的数据 不进行拷贝
				continue;
			}
			
			newVal[iterVal.key().asString()]["pid"] = (*iterVal)["pid"];
			newVal[iterVal.key().asString()]["cid"] = (*iterVal)["cid"];
			newVal[iterVal.key().asString()]["winlose"] = (*iterVal)["winlose"];
			newVal[iterVal.key().asString()]["player_count"] = (*iterVal)["player_count"];
			newVal[iterVal.key().asString()]["player_status"] = (*iterVal)["player_status"];
			
			if((*iterVal).isMember("pos"))
				newVal[iterVal.key().asString()]["pos"] = (*iterVal)["pos"];
			
			newVal[iterVal.key().asString()]["name"] = (*iterVal)["name"];
			newVal[iterVal.key().asString()]["desc"] = (*iterVal)["desc"];
		}
		
		if(newVal.size())
		{
			cb.player = w.write(newVal);
		}
		else
		{
			cb.player = "";
		}
	}
	else
	{
		cb.player = w.write(val);
	}
	
	UpdateCenterBattle(cb);
	return true;
}

// 开始新的一局
bool CenterBattleManager::StartNewLoop(const uint32 & cb_id, std::vector<uint32> del_chars, std::vector<uint32> playing_chars)
{
// WGS_CENTERBATTLE_LOCK
	CenterBattle cb;
	if(!GetCenterBattle(cb_id, &cb))
		return false;
	
	// 删除玩家数据或者更新玩家状态（如果玩家在组局中有记录，更新玩家状态为离开，不清除玩家数据）
	Json::Reader reader;
	Json::Value val, newVal;
	reader.parse(cb.player, val);
	
	// 先更新游戏中玩家状态
	std::vector<uint32>::iterator itPl, eiPl = playing_chars.end();
	for(itPl = playing_chars.begin(); itPl!=eiPl; ++itPl)
	{
		for(Json::Value::iterator iterVal=val.begin(); iterVal!=val.end(); ++iterVal)
		{
			if(*itPl == (*iterVal)["cid"].asUInt())
			{// 更新玩家游戏中状态
				(*iterVal)["player_status"] = enCenterBattlePlayerStatus_Playing;
				break;
			}
		}
	}
	
	bool bRemove = false;
	
	// 删除没有游戏记录的玩家
	for(Json::Value::iterator iterVal=val.begin(); iterVal!=val.end(); ++iterVal)
	{
		bool bFindChar = false;
		std::vector<uint32>::iterator itDel, eiDel = del_chars.end();
		for(itDel = del_chars.begin(); itDel!=eiDel; ++itDel)
		{
			if(*itDel == (*iterVal)["cid"].asUInt())
			{// 找到要更新的玩家
				bFindChar = true;
				bRemove = true;
				break;
			}
		}
		
		if(!bFindChar)
		{
			newVal[iterVal.key().asString()]["pid"] = (*iterVal)["pid"];
			newVal[iterVal.key().asString()]["cid"] = (*iterVal)["cid"];
			newVal[iterVal.key().asString()]["winlose"] = (*iterVal)["winlose"];
			newVal[iterVal.key().asString()]["player_count"] = (*iterVal)["player_count"];
			newVal[iterVal.key().asString()]["player_status"] = (*iterVal)["player_status"];
			if((*iterVal).isMember("pos"))
				newVal[iterVal.key().asString()]["pos"] = (*iterVal)["pos"];
			
			newVal[iterVal.key().asString()]["name"] = (*iterVal)["name"];
			newVal[iterVal.key().asString()]["desc"] = (*iterVal)["desc"];
		}
		
	}
	
	Json::FastWriter w;
	if(bRemove)
	{// 有删除玩家数据
		cb.player = w.write(newVal);
	}
	else
	{// 没有删除玩家数据
		cb.player = w.write(val);
	}
	
	cb.curr_loop++;
	cb.status = enBattleStatus_playing;
	return UpdateCenterBattle(cb);
}

// 组局结束
bool CenterBattleManager::CenterBattleComplate(const uint32 & cb_id, const uint8 nExitType)
{
WGS_CENTERBATTLE_LOCK
	
	CenterBattle cb;
	if(!GetCenterBattle(cb_id, &cb))
		return false;
	
	if(nExitType)
	{
		String szTitle;
		char buf[256] = "";
		
		String item_name = sXmlDataMgr.GetItemModelNameByAgentID(cb.reg_from, cb.data1);
		stCenterBattleOpenCoins stCBOC = sXmlDataMgr.GetCenterBattleOpenCoins(cb.reg_from, cb.game_id, cb.limit_loop, enCenterBattleLimitType_Loop, cb.mode);
		switch(nExitType)
		{
			case enCenterBattleReturnGold_ServerRestart:	// 重启
				{
					if(cb.data1 && cb.pay_mode == enPayMode_FangZhu)
					{// 返还报名费邮件（带附件）
						const MailModel *pModel = sXmlDataMgr.GetMailModel("CENTER_BATTLE_SERVER_RESTART");
						if(pModel)
						{
							szTitle = pModel->szTitle;
							String szContent = pModel->szContent;
							//  由于服务器非正常启动，您于%s创建的房间ID为【%s】【%s】的牌局解散，返还房费【%sx%u】！
							sprintf(buf, szContent.c_str(), cb.create_time.c_str(), cb.join_code.c_str(), stCBOC.desc.c_str(), item_name.c_str(), cb.data2);
						}
					}
					else
					{// 不返还报名费邮件
						const MailModel *pModel = sXmlDataMgr.GetMailModel("CENTER_BATTLE_SERVER_RESTART_FREE");
						if(pModel)
						{
							szTitle = pModel->szTitle;
							String szContent = pModel->szContent;
							//  由于服务器非正常启动，您于%s创建的房间ID为【%s】【%s】的牌局解散！
							sprintf(buf, szContent.c_str(), cb.create_time.c_str(), cb.join_code.c_str(), stCBOC.desc.c_str());
						}
					}
				}
				break;
			case enCenterBattleReturnGold_TimeOut:			// 超时
				{
					if(cb.data1 && cb.pay_mode == enPayMode_FangZhu)
					{
						const MailModel *pModel = sXmlDataMgr.GetMailModel("CENTER_BATTLE_TIMEOVER");
						if(pModel)
						{
							szTitle = pModel->szTitle;
							String szContent = pModel->szContent;
							//  您于%s创建的房间ID为【%s】【%s】的牌桌超时，返还房费【%sx%u】!！
							sprintf(buf, szContent.c_str(), cb.create_time.c_str(), cb.join_code.c_str(), stCBOC.desc.c_str(), item_name.c_str(), cb.data2);				
						}
					}
					else
					{
						const MailModel *pModel = sXmlDataMgr.GetMailModel("CENTER_BATTLE_TIMEOVER_FREE");
						if(pModel)
						{
							szTitle = pModel->szTitle;
							String szContent = pModel->szContent;
							//  您于%s创建的房间ID为【%s】【%s】的牌桌超时!！
							sprintf(buf, szContent.c_str(), cb.create_time.c_str(), cb.join_code.c_str(), stCBOC.desc.c_str());				
						}
					}
				}
				break;
			case enCenterBattleReturnGold_OwnerDissolve:	// 未开局
				{
					if(cb.data1 && cb.pay_mode == enPayMode_FangZhu)
					{
						const MailModel *pModel = sXmlDataMgr.GetMailModel("CENTER_BATTLE_DISSOLVE");
						if(pModel)
						{
							szTitle = pModel->szTitle;
							String szContent = pModel->szContent;
							//  您于%s创建的房间ID为【%s】【%s】的牌桌解散了，返还房费【%sx%u】！
							sprintf(buf, szContent.c_str(), cb.create_time.c_str(), cb.join_code.c_str(), stCBOC.desc.c_str(), item_name.c_str(), cb.data2);
						}
					}
					else
					{
						const MailModel *pModel = sXmlDataMgr.GetMailModel("CENTER_BATTLE_DISSOLVE_FREE");
						if(pModel)
						{
							szTitle = pModel->szTitle;
							String szContent = pModel->szContent;
							//  您于%s创建的房间ID为【%s】【%s】的牌桌解散了！
							sprintf(buf, szContent.c_str(), cb.create_time.c_str(), cb.join_code.c_str(), stCBOC.desc.c_str());		
						}
					}
				}
				break;
			case enCenterBattleReturnGold_ForceTime:	// 强制开始
				{
					if(cb.data1 && cb.pay_mode == enPayMode_FangZhu)
					{
						const MailModel *pModel = sXmlDataMgr.GetMailModel("CENTER_BATTLE_FORCETIME");
						if(pModel)
						{
							szTitle = pModel->szTitle;
							String szContent = pModel->szContent;
							//  您于%s创建的房间ID为【%s】【%s】的牌桌规定时间内未开始，牌桌解散，返还房费【%sx%u】!
							sprintf(buf, szContent.c_str(), cb.create_time.c_str(), cb.join_code.c_str(), stCBOC.desc.c_str(), item_name.c_str(), cb.data2);
						}
					}
					else
					{
						const MailModel *pModel = sXmlDataMgr.GetMailModel("CENTER_BATTLE_FORCETIME_FREE");
						if(pModel)
						{
							szTitle = pModel->szTitle;
							String szContent = pModel->szContent;
							//  您于%s创建的房间ID为【%s】【%s】的牌桌规定时间内未开始，牌桌解散!
							sprintf(buf, szContent.c_str(), cb.create_time.c_str(), cb.join_code.c_str(), stCBOC.desc.c_str());		
						}
					}
				}
			break;
			default:
				break;
		}
		
		std::map<uint32,uint32> mapItems;
		// 邮件附件方式返还房卡
		/* 
		if(cb.data1 > 0)
		{
			mapItems.insert(std::make_pair(cb.data1, cb.data2));
		}
		
		sGLMgr.CreateMail(cb.pid, szTitle, buf, 0, en_ST_ReturnCenterBattleOpenCoins, &mapItems); */
		
		// AA制和房主全额制退房费（直接加，不以邮件附件来）
		if(cb.data1 > 0)
		{
			Json::Value valPay;
			Json::Reader reader;
			Json::FastWriter w;
			reader.parse(cb.sdata4, valPay);
			
			if(cb.pay_mode == enPayMode_AAPay)
			{// AA制
				for(Json::Value::iterator iterVal=valPay.begin(); iterVal!=valPay.end(); ++iterVal)
				{
					uint32 char_id = (*iterVal)["cid"].asUInt();
					CharPtr pChr = sCharMgr.load(char_id);
					if(pChr.isNull())
						continue;
					
					sGLMgr.addItemNum(pChr, cb.data1, cb.data2);
					sLogDataMgr.UpdateItemsInfoLog(pChr, en_ST_ReturnCenterBattleOpenCoins, cb.data1, en_UNT_Add, cb.data2, cb.cb_id);
					
					uint32 pid = (*iterVal)["pid"].asUInt();
					sGLMgr.CreateMail(pid, szTitle, buf, 0, en_ST_ReturnCenterBattleOpenCoins, &mapItems);
				}
			}
			else if(cb.pay_mode == enPayMode_FangZhu)
			{// 房主全额制
				for(Json::Value::iterator iterVal=valPay.begin(); iterVal!=valPay.end(); ++iterVal)
				{
					uint32 gz_id = (*iterVal)["gz_id"].asUInt();
					uint32 game_id = sGLMgr.GetTargetServerGameid(gz_id, cb.reg_from);
					if(sXmlDataMgr.IsInGameIds(game_id))
					{// 房主在同一服务器
						uint32 char_id = (*iterVal)["cid"].asUInt();
						CharPtr pChr = sCharMgr.load(char_id);
						if(pChr.isNull())
							break;
						
						sGLMgr.addItemNum(pChr, cb.data1, cb.data2);
						sLogDataMgr.UpdateItemsInfoLog(pChr, en_ST_ReturnCenterBattleOpenCoins, cb.data1, en_UNT_Add, cb.data2, cb.cb_id);
						
						uint32 pid = (*iterVal)["pid"].asUInt();
						sGLMgr.CreateMail(pid, szTitle, buf, 0, en_ST_ReturnCenterBattleOpenCoins, &mapItems);
					}
					else
					{// 给棋牌圈玩家加上房卡
						Json::Value valData = (*iterVal);
						
						valData["cb_id"] = cb.cb_id;
						valData["mail_title"] = szTitle;
						valData["content"] = buf;
						valData["agent_id"] = cb.reg_from;
						
						String strData = w.write(valData);
						sGLMgr.SendAddItemGateway(strData);
					}
				}
			}
		}
		else
		{
			sGLMgr.CreateMail(cb.pid, szTitle, buf, 0, en_ST_ReturnCenterBattleOpenCoins, &mapItems);
		}
		
	}
	
	cb.status = enBattleStatus_Delete;
	cb.end_time = sGLMgr.GetCurDateTime();
	
	sLogDataMgr.CreateCenterBattleLog(cb.pid, cb.cb_id, cb.game_id, cb.gz_id, cb.data1, cb.data2, nExitType, cb.curr_loop, cb.curr_loop == cb.limit_loop, cb.mode);
	
	// 遍历玩家列表，给每个玩家加上日志
	Json::Reader reader;
	Json::Value val;
	reader.parse(cb.player, val);
	
	for(Json::Value::iterator iterVal=val.begin(); iterVal!=val.end(); ++iterVal)
	{
		uint32 char_id = (*iterVal)["cid"].asUInt();
		CharPtr pChr = sCharMgr.getByHandle(char_id);
		if(pChr.isNull())
		{
			pChr = sCharMgr.load(char_id);
			if(pChr.isNull())
				continue;
		}
		
		sLogDataMgr.CenterBattleResultLog(pChr,cb,
										(*iterVal)["player_count"].asUInt(),
										(*iterVal)["winlose"].asInt(),
										nExitType,
										(*iterVal)["pid"].asUInt() == cb.pid);
	}
	
	if(nExitType == 0)
	{
		for(Json::Value::iterator iterVal=val.begin(); iterVal!=val.end(); ++iterVal)
		{
			uint32 pid = (*iterVal)["pid"].asUInt();
			
			CRUser cru;
			if(sCRUsersMgr.GetCRUser(pid, &cru))
			{
				Fields fields;
				fields["play_game_count"] = cru.play_game_count + 1;
				sCRUsersMgr.UpdateCRUser(pid, &fields);
			}
		}
		
		CRUser cru;
		if(sCRUsersMgr.GetCRUser(cb.pid, &cru))
		{// 房主创建次数成功
			Fields fields;
			fields["start_game_count"] = cru.start_game_count + 1;
			sCRUsersMgr.UpdateCRUser(cb.pid, &fields);
		}
	}
	
	UpdateCenterBattle(cb);
	return true;
}

// 设置组局牌桌为运行中等待玩家开始
void CenterBattleManager::SetCentetBattleProcess(const uint32 & cb_id)
{
WGS_CENTERBATTLE_LOCK
	
	CenterBattle cb;
	if(!GetCenterBattle(cb_id, &cb))
		return ;
	
	cb.status = enBattleStatus_Process;
	UpdateCenterBattle(cb);
}

// 更新当前局数
bool CenterBattleManager::UpdateCenterBattleCurrloop(const uint32 & cb_id, const uint32 & loop)
{
/* WGS_CENTERBATTLE_LOCK
	CenterBattle cb;
	if(!GetCenterBattle(cb_id, &cb))
		return false;
	
	cb.curr_loop = loop;
	UpdateCenterBattle(cb); */
	return true;
}

// AA制扣除玩家房卡
bool CenterBattleManager::ReducePlayerAADiamand(const uint32 & cb_id, std::map<uint32, uint32> vPCid, const uint32 & reduce_num)
{
	if(vPCid.empty())
		return false;
	
	// 获得组局信息
	CenterBattle cb;
	GetCenterBattle(cb_id, &cb);
	
	// 读取付过房费的玩家
	Json::Value val;
	Json::Reader reader;
	reader.parse(cb.sdata4, val);
	
	if(val.size())
	{
		std::map<uint32, uint32>::iterator itPid, eiPid = vPCid.end();
		for(itPid = vPCid.begin(); itPid!=eiPid; ++itPid)
		{
			bool bFind = false;
			for(Json::Value::iterator iterVal = val.begin(); iterVal != val.end(); ++iterVal)
			{
				uint32 pid = (*iterVal)["pid"].asUInt();				// 玩家PID
				if(pid == itPid->first)
				{
					bFind = true;
					break;
				}
			}
			
			if(bFind)
				continue;
			
			Json::Value val2;
			val2["pid"] = itPid->first;
			val2["cid"] = itPid->second;
			val2["model_id"] = uint32(ItemModel_DiamondOpen);
			val2["num"] = reduce_num;
			
			val[val.size() - 1] = val2;
		}
	}
	else
	{// 空列表
		uint8 index = 0;
		std::map<uint32, uint32>::iterator itPid, eiPid = vPCid.end();
		for(itPid = vPCid.begin(); itPid!=eiPid; ++itPid)
		{
			Json::Value val2;
			val2["pid"] = itPid->first;
			val2["cid"] = itPid->second;
			val2["model_id"] = uint32(ItemModel_DiamondOpen);
			val2["num"] = reduce_num;
			
			val[index++] = val2;
		}
	}
	
	Json::FastWriter w;
	cb.sdata4 = w.write(val);
	UpdateCenterBattle(cb);
	return true;
}

// 获取某游戏公共房列表
std::list<CenterBattle> CenterBattleManager::GetPublicCenterBattleList(const uint32 & agent_id, const uint32 & game_id)
{
	std::list<CenterBattle> lstData;
	GetCenterBattleList(&lstData, "status < 255 and reg_from = %u and game_id = %u and (`istrack` = 1 or `istrack` = 2)", agent_id, game_id);
	
	return lstData;
}

// 获取组局房间ID
String CenterBattleManager::GetCenterBattleJoinCode(const uint32 & cb_id)
{
	if(cb_id == 0)
		return "";
	
WGS_CENTERBATTLE_LOCK
	CenterBattle cb;
	GetCenterBattle(cb_id, &cb);
	
	return cb.join_code;
}

// 机器人进入组局
void CenterBattleManager::RobotJoinCenterBattle(CharPtr & pChr, const uint32 & cb_id, const uint32 & pos)
{
	if(pChr.isNull() || cb_id == 0)
		return ;
	
	UserPtr pUser = sUserMgr.load(pChr->getUInt32Field("userid"));
	if(pUser.isNull())
		return ;
	
	CenterBattle cb;
	GetCenterBattle(cb_id, &cb);
	
	if(cb.cb_id == 0)
		return ;
	
	Json::Reader reader;
	Json::Value val;
	reader.parse(cb.player, val);
	
	bool bFindChar = false;
	for(Json::Value::iterator iterVal=val.begin(); iterVal!=val.end(); ++iterVal)
	{
		// if(pChr->getHandle() == (*iterVal)["cid"].asUInt())
		if(pUser->getUInt32Field("platform_id") == (*iterVal)["pid"].asUInt())
		{
			bFindChar = true;
			(*iterVal)["player_status"] = enCenterBattlePlayerStatus_Free;	//空闲
			(*iterVal)["cid"] = uint32(pChr->getHandle());					//char_id
			break;
		}
	}
	
	if(!bFindChar)
	{// 新增加玩家数据
		
		char str[256] = "";
		sprintf(str, "%u", uint32(pUser->getUInt32Field("platform_id")));
		
		val[str]["pid"] = pUser->getUInt32Field("platform_id");				// PID
		val[str]["cid"] = uint32(pChr->getHandle());						// CID
		val[str]["name"] = string_url_encode(pChr->getStringField("name")); // 昵称
		val[str]["desc"] = string_url_encode(pChr->getStringField("desc"));	// 头像
		val[str]["winlose"] = 0;											// 输赢积分
		val[str]["player_count"] = 0;										// 总游戏局属
		val[str]["player_status"] = enCenterBattlePlayerStatus_Free;		// 角色状态（空闲 游戏中 离开 结束游戏）
		if(pos != 255)
		{
			val[str]["pos"] = pos;											// 设置座位属性
		}
	}
	
	Json::FastWriter w;
	cb.player = w.write(val);
	
	// 将角色ID加入进入过的列表
	String strJoinPlayers = cb.sdata1;
	if(strJoinPlayers.empty())
	{
		strJoinPlayers += "|";
		strJoinPlayers += StringConverter::toString(pUser->getUInt32Field("platform_id"));
		strJoinPlayers += "|";
		
		cb.sdata1 = strJoinPlayers;
	}
	else
	{
		bool bFindChar = false;
		std::vector<String> vStr = StringUtil::split(strJoinPlayers,"|");
		std::vector<String>::iterator iter,ei = vStr.end();
		for(iter = vStr.begin(); iter!=ei; ++iter)
		{
			if(StringConverter::parseUnsignedInt(*iter) == pUser->getUInt32Field("platform_id"))
			{
				bFindChar = true;
				break;
			}
		}
		
		if(!bFindChar)
		{// 增加玩家ID到进入列表中
			strJoinPlayers += StringConverter::toString(pUser->getUInt32Field("platform_id"));
			strJoinPlayers += "|";
			cb.sdata1 = strJoinPlayers;
		}
	}
	
	{
	WGS_CENTERBATTLE_LOCK
		UpdateCenterBattle(cb);
	}
}

//=============================组局信息相关===================================


//=============================玩家组局信息相关===================================
// 添加玩家组局信息
bool CenterBattleUserManager::AddCenterBattleUser(CenterBattleUser & cbu)
{
	Fields fields;
	sDataMgr.initData(DataManager::DatabaseTypeCenter, DB_NAME_CENTERBATTLEUSER, &fields);
	
	fields["status"] = cbu.status;						// 状态（0 无效 1 空闲 2 牌局中  255 结束）
	fields["cb_id"] = cbu.cb_id;						// 组局ID
	fields["platform_id"] = cbu.platform_id;			// 玩家PID
	fields["name"] = cbu.name;							// 玩家昵称
	fields["head"] = cbu.head;							// 玩家头像
	fields["is_room_owner"] = cbu.is_room_owner;		// 玩家是否房主
	fields["is_in_blacklist"] = cbu.is_in_blacklist;	// 玩家是否在黑名单中
	fields["loop"] = cbu.loop;							// 游戏局数
	fields["curr_score"] = cbu.curr_score;				// 当前积分
	fields["create_time"] = cbu.create_time;			// 创建时间
	fields["end_time"] = cbu.end_time;					// 结束时间
	fields["data1"] = cbu.data1;						// 附加数据1
	fields["data2"] = cbu.data2;						// 附加数据2
	fields["data3"] = cbu.data3;						// 附加数据3
	fields["data4"] = cbu.data4;						// 附加数据4
	
	if (!sDataMgr.insertData(DataManager::DatabaseTypeCenter, DB_NAME_CENTERBATTLEUSER, &fields))
		return false;
	
	cbu.serial = fields["serial"].GetUInt32();
	return true;
}

// 更新玩家组局信息
bool CenterBattleUserManager::UpdateCenterBattleUser(const CenterBattleUser & cbu, uint32 update_key )
{
	Fields fields;
	fields["status"] = cbu.status;						// 状态
	fields["cb_id"] = cbu.cb_id;						// 组局ID
	fields["platform_id"] = cbu.platform_id;			// 玩家PID
	fields["name"] = cbu.name;							// 玩家昵称
	fields["head"] = cbu.head;							// 玩家头像
	fields["is_room_owner"] = cbu.is_room_owner;		// 玩家是否房主
	fields["is_in_blacklist"] = cbu.is_in_blacklist;	// 玩家是否在黑名单中
	fields["loop"] = cbu.loop;							// 游戏局数
	fields["curr_score"] = cbu.curr_score;				// 当前积分
	fields["create_time"] = cbu.create_time;			// 创建时间
	fields["end_time"] = cbu.end_time;					// 结束时间
	fields["data1"] = cbu.data1;						// 附加数据1
	fields["data2"] = cbu.data2;						// 附加数据2
	fields["data3"] = cbu.data3;						// 附加数据3
	fields["data4"] = cbu.data4;						// 附加数据4
	
	int count = sDataMgr.updateDataQueryAffected(DataManager::DatabaseTypeCenter, DB_NAME_CENTERBATTLEUSER, 
								&fields, "`serial` = %u", cbu.serial);
	return count > 0;
}

bool CenterBattleUserManager::UpdateCenterBattleUser(Fields * fields, const char * QueryString, ...)
{
	char sql[SQLBUFER_LEN] = ""; 
	va_list vlist; 
	va_start(vlist, QueryString); 
	vsnprintf(sql, SQLBUFER_LEN, QueryString, vlist); 
	va_end(vlist);
	int count = sDataMgr.updateDataQueryAffected(DataManager::DatabaseTypeCenter, DB_NAME_CENTERBATTLEUSER, fields, sql);
	return count > 0;
}

bool CenterBattleUserManager::UpdateCenterBattleUser(const uint32 &cbu_id, Fields * fields)
{
	int count = sDataMgr.updateDataQueryAffected(DataManager::DatabaseTypeCenter, DB_NAME_CENTERBATTLEUSER, 
															fields, "`serial` = %u", cbu_id);
	
	return count > 0;
}

// 获取玩家组局信息
bool CenterBattleUserManager::GetCenterBattleUser(const uint32 & serial, CenterBattleUser * cbu)
{
	FieldRows rows;
	sDataMgr.getDatas(DataManager::DatabaseTypeCenter, DB_NAME_CENTERBATTLEUSER, &rows, "`serial` = %u", serial);
	if (rows.empty())
		return false;
	
	Fields fields = rows.front();
	cbu->serial = fields["serial"].GetUInt32();
	cbu->status = fields["status"].GetUInt8();
	cbu->cb_id = fields["cb_id"].GetUInt32();
	cbu->platform_id = fields["platform_id"].GetUInt32();
	
	cbu->name = fields["name"].GetValue();
	cbu->head = fields["head"].GetValue();
	
	cbu->is_room_owner = fields["is_room_owner"].GetUInt8();
	cbu->is_in_blacklist = fields["is_in_blacklist"].GetUInt8();
	
	cbu->loop = fields["loop"].GetUInt32();
	cbu->curr_score = fields["curr_score"].GetUInt32();
	
	cbu->create_time = fields["create_time"].GetValue();
	cbu->end_time = fields["end_time"].GetValue();
	
	cbu->data1 = fields["data1"].GetUInt32();
	cbu->data2 = fields["data2"].GetUInt32();
	cbu->data3 = fields["data3"].GetUInt32();
	cbu->data4 = fields["data4"].GetUInt32();
	return true;
}

// 获取玩家组局信息列表
uint32 CenterBattleUserManager::GetCenterBattleUserList(std::list<CenterBattleUser> * lstData, const char * query,...)
{
	va_list argp;
	va_start(argp, query);
	lstData->clear();
	FieldRows fieldRows;
	
	char sql[SQLBUFER_LEN] = ""; 
	va_list vlist; 
	va_start(vlist, query); 
	vsnprintf(sql, SQLBUFER_LEN, query, vlist); 
	va_end(vlist);
	
	if (!sDataMgr.getDatas(DataManager::DatabaseTypeCenter, DB_NAME_CENTERBATTLEUSER, &fieldRows, sql))
		return 0;
	
	FieldRows::iterator iter, enditer = fieldRows.end();
	for (iter = fieldRows.begin(); iter != enditer; ++ iter)
	{
		CenterBattleUser cbu;
		Fields &fields = *iter;
		
		cbu.serial = fields["serial"].GetUInt32();
		cbu.status = fields["status"].GetUInt8();
		cbu.cb_id = fields["cb_id"].GetUInt32();
		cbu.platform_id = fields["platform_id"].GetUInt32();
		
		cbu.name = fields["name"].GetValue();
		cbu.head = fields["head"].GetValue();
		
		cbu.is_room_owner = fields["is_room_owner"].GetUInt8();
		cbu.is_in_blacklist = fields["is_in_blacklist"].GetUInt8();
		
		cbu.loop = fields["loop"].GetUInt32();
		cbu.curr_score = fields["curr_score"].GetUInt32();
		
		cbu.create_time = fields["create_time"].GetValue();
		cbu.end_time = fields["end_time"].GetValue();
		
		cbu.data1 = fields["data1"].GetUInt32();
		cbu.data2 = fields["data2"].GetUInt32();
		cbu.data3 = fields["data3"].GetUInt32();
		cbu.data4 = fields["data4"].GetUInt32();
		
		lstData->push_back(cbu);
	}
	
	return lstData->size();
}

// 获取玩家组局信息
bool CenterBattleUserManager::GetCenterBattleUser(const uint32 & cb_id, const uint32 & platform_id, CenterBattleUser * cbu)
{
WGS_CBUSER_LOCK
	
	std::list<CenterBattleUser> lstData;
	GetCenterBattleUserList(&lstData, " `status` < 255 and `cb_id` = %u and `platform_id` = %u", cb_id, platform_id);
	if(lstData.empty())
		return false;
	
	cbu = &(*lstData.begin());
	return true;
}

//=============================玩家组局信息相关===================================



